text:
package org.jf.dexlib.Code.Analysis;

import org.jf.dexlib.*;
import org.jf.dexlib.Util.AccessFlags;
import org.jf.dexlib.Util.ExceptionWithContext;
import org.jf.dexlib.Util.SparseArray;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.File;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static org.jf.dexlib.ClassDataItem.EncodedField;
import static org.jf.dexlib.ClassDataItem.EncodedMethod;

public class ClassPath {
    private static ClassPath theClassPath = null;

    /**
     * The current version of dalvik in master(AOSP) has a slight change to the way the
     * virtual tables are computed. This should be set to true to use the new logic.
     * TODO: set this based on api level, once it's present in a released version of Android
     */
    private boolean checkPackagePrivateAccess;

    private final HashMap<String, ClassDef> classDefs;
    protected ClassDef javaLangObjectClassDef; //cached ClassDef for Ljava/lang/Object;

    // Contains the classes that we haven't loaded yet
    private HashMap<String, UnresolvedClassInfo> unloadedClasses;

    private static final Pattern dalvikCacheOdexPattern = Pattern.compile("@([^@]+)@classes.dex$");

    /**
     * Initialize the class path using the dependencies from an odex file
     * @param classPathDirs The directories to search for boot class path files
     * @param extraBootClassPathEntries any extra entries that should be added after the entries that are read
     * from the odex file
     * @param dexFilePath The path of the dex file (used for error reporting purposes only)
     * @param dexFile The DexFile to load - it must represents an odex file
     */
    public static void InitializeClassPathFromOdex(String[] classPathDirs, String[] extraBootClassPathEntries,
                                                   String dexFilePath, DexFile dexFile,
                                                   boolean checkPackagePrivateAccess) {
        if (!dexFile.isOdex()) {
            throw new ExceptionWithContext("Cannot use InitialiazeClassPathFromOdex with a non-odex DexFile");
        }

        if (theClassPath != null) {
            throw new ExceptionWithContext("Cannot initialize ClassPath multiple times");
        }

        OdexDependencies odexDependencies = dexFile.getOdexDependencies();

        String[] bootClassPath = new String[odexDependencies.getDependencyCount()];
        for (int i=0; i<bootClassPath.length; i++) {
            String dependency = odexDependencies.getDependency(i);

            if (dependency.endsWith(".odex")) {
                int slashIndex = dependency.lastIndexOf("/");

                if (slashIndex != -1) {
                    dependency = dependency.substring(slashIndex+1);
                }
            } else if (dependency.endsWith("@classes.dex")) {
                Matcher m = dalvikCacheOdexPattern.matcher(dependency);

                if (!m.find()) {
                    throw new ExceptionWithContext(String.format("Cannot parse dependency value %s", dependency));
                }

                dependency = m.group(1);
            } else {
                throw new ExceptionWithContext(String.format("Cannot parse dependency value %s", dependency));
            }

            bootClassPath[i] = dependency;
        }

        theClassPath = new ClassPath();
        theClassPath.initClassPath(classPathDirs, bootClassPath, extraBootClassPathEntries, dexFilePath, dexFile,
                checkPackagePrivateAccess);
    }

    /**
     * Initialize the class path using the given boot class path entries
     * @param classPathDirs The directories to search for boot class path files
     * @param bootClassPath A list of the boot class path entries to search for and load
     * @param dexFilePath The path of the dex file (used for error reporting purposes only)
     * @param dexFile the DexFile to load
     * classes
     */
    public static void InitializeClassPath(String[] classPathDirs, String[] bootClassPath,
                                           String[] extraBootClassPathEntries, String dexFilePath, DexFile dexFile,
                                           boolean checkPackagePrivateAccess) {
        if (theClassPath != null) {
            throw new ExceptionWithContext("Cannot initialize ClassPath multiple times");
        }

        theClassPath = new ClassPath();
        theClassPath.initClassPath(classPathDirs, bootClassPath, extraBootClassPathEntries, dexFilePath, dexFile,
                checkPackagePrivateAccess);
    }

    private ClassPath() {
        classDefs = new HashMap<String, ClassDef>();
    }

    private void initClassPath(String[] classPathDirs, String[] bootClassPath, String[] extraBootClassPathEntries,
                               String dexFilePath, DexFile dexFile, boolean checkPackagePrivateAccess) {
        this.checkPackagePrivateAccess = checkPackagePrivateAccess;
        unloadedClasses = new LinkedHashMap<String, UnresolvedClassInfo>();

        if (bootClassPath != null) {
            for (String bootClassPathEntry: bootClassPath) {
                loadBootClassPath(classPathDirs, bootClassPathEntry);
            }
        }

        if (extraBootClassPathEntries != null) {
            for (String bootClassPathEntry: extraBootClassPathEntries) {
                loadBootClassPath(classPathDirs, bootClassPathEntry);
            }
        }

        if (dexFile != null) {
            loadDexFile(dexFilePath, dexFile);
        }

        javaLangObjectClassDef = getClassDef("Ljava/lang/Object;", false);

        for (String primitiveType: new String[]{"Z", "B", "S", "C", "I", "J", "F", "D"}) {
            ClassDef classDef = new PrimitiveClassDef(primitiveType);
            classDefs.put(primitiveType, classDef);
        }
    }

    private void loadBootClassPath(String[] classPathDirs, String bootClassPathEntry) {
        for (String classPathDir: classPathDirs) {
            File file = null;
            DexFile dexFile = null;

            int extIndex = bootClassPathEntry.lastIndexOf(".");

            String baseEntry;
            if (extIndex == -1) {
                baseEntry = bootClassPathEntry;
            } else {
                baseEntry = bootClassPathEntry.substring(0, extIndex);
            }

            for (String ext: new String[]{"", ".odex", ".jar", ".apk", ".zip"}) {
                if (ext.length() == 0) {
                    file = new File(classPathDir, bootClassPathEntry);
                } else {
                    file = new File(classPathDir, baseEntry + ext);
                }

                if (file.exists()) {
                    if (!file.canRead()) {
                        System.err.println(String.format("warning: cannot open %s for reading. Will continue " +
                                "looking.", file.getPath()));
                        continue;
                    }

                    try {
                        dexFile = new DexFile(file, false, true);
                    } catch (DexFile.NoClassesDexException ex) {
                        continue;
                    } catch (Exception ex) {
                        throw ExceptionWithContext.withContext(ex, "Error while reading boot class path entry \"" +
                        bootClassPathEntry + "\".");
                    }
                }
            }
            if (dexFile == null) {
                continue;
            }

            try {
                loadDexFile(file.getPath(), dexFile);
            } catch (Exception ex) {
                throw ExceptionWithContext.withContext(ex,
                        String.format("Error while loading boot classpath entry %s", bootClassPathEntry));
            }
            return;
        }
        throw new ExceptionWithContext(String.format("Cannot locate boot class path file %s", bootClassPathEntry));
    }

    private void loadDexFile(String dexFilePath, DexFile dexFile) {
        for (ClassDefItem classDefItem: dexFile.ClassDefsSection.getItems()) {
            try {
                UnresolvedClassInfo unresolvedClassInfo = new UnresolvedClassInfo(dexFilePath, classDefItem);

                if (!unloadedClasses.containsKey(unresolvedClassInfo.classType)) {
                    unloadedClasses.put(unresolvedClassInfo.classType, unresolvedClassInfo);
                }
            } catch (Exception ex) {
                throw ExceptionWithContext.withContext(ex, String.format("Error while loading class %s",
                        classDefItem.getClassType().getTypeDescriptor()));
            }
        }
    }

    /**
     * This method loads the given class (and any dependent classes, as needed), removing them from unloadedClasses
     * @param classType the class to load
     * @return the newly loaded ClassDef object for the given class, or null if the class cannot be found
     */
    @Nullable
    private static ClassDef loadClassDef(String classType) {
        ClassDef classDef = null;

        UnresolvedClassInfo classInfo = theClassPath.unloadedClasses.get(classType);
        if (classInfo == null) {
            return null;
        }

        try {
            classDef = new ClassDef(classInfo);
            theClassPath.classDefs.put(classDef.classType, classDef);
        } catch (Exception ex) {
            throw ExceptionWithContext.withContext(ex, String.format("Error while loading class %s from file %s",
                    classInfo.classType, classInfo.dexFilePath));
        }
        theClassPath.unloadedClasses.remove(classType);

        return classDef;
    }

    @Nonnull
    public static ClassDef getClassDef(String classType, boolean createUnresolvedClassDef)  {
        ClassDef classDef = theClassPath.classDefs.get(classType);
        if (classDef == null) {
            //if it's an array class, try to create it
            if (classType.charAt(0) == '[') {
                return theClassPath.createArrayClassDef(classType);
            } else {
                try {
                    classDef = loadClassDef(classType);
                    if (classDef == null) {
                        throw new ExceptionWithContext(
                                String.format("Could not find definition for class %s", classType));
                    }
                } catch (Exception ex) {
                    RuntimeException exWithContext = ExceptionWithContext.withContext(ex,
                            String.format("Error while loading ClassPath class %s", classType));
                    if (createUnresolvedClassDef) {
                        //TODO: add warning message
                        return theClassPath.createUnresolvedClassDef(classType);
                    } else {
                        throw exWithContext;
                    }
                }
            }
        }
        return classDef;
    }

    public static ClassDef getClassDef(String classType) {
        return getClassDef(classType, true);
    }

    public static ClassDef getClassDef(TypeIdItem classType) {
        return getClassDef(classType.getTypeDescriptor());
    }

    public static ClassDef getClassDef(TypeIdItem classType, boolean creatUnresolvedClassDef) {
        return getClassDef(classType.getTypeDescriptor(), creatUnresolvedClassDef);
    }

    //256 [ characters
    private static final String arrayPrefix = "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[" +
        "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[" +
        "[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[";
    private static ClassDef getArrayClassDefByElementClassAndDimension(ClassDef classDef, int arrayDimension) {
        return getClassDef(arrayPrefix.substring(256 - arrayDimension) + classDef.classType);
    }

    private static ClassDef unresolvedObjectClassDef = null;
    public static ClassDef getUnresolvedObjectClassDef() {
        if (unresolvedObjectClassDef == null) {
            unresolvedObjectClassDef = new UnresolvedClassDef("Ljava/lang/Object;");
        }
        return unresolvedObjectClassDef;
    }

    private ClassDef createUnresolvedClassDef(String classType)  {
        assert classType.charAt(0) == 'L';

        UnresolvedClassDef unresolvedClassDef = new UnresolvedClassDef(classType);
        classDefs.put(classType, unresolvedClassDef);
        return unresolvedClassDef;
    }

    private ClassDef createArrayClassDef(String arrayClassName) {
        assert arrayClassName != null;
        assert arrayClassName.charAt(0) == '[';

        ArrayClassDef arrayClassDef = new ArrayClassDef(arrayClassName);
        if (arrayClassDef.elementClass == null) {
            return null;
        }

        classDefs.put(arrayClassName, arrayClassDef);
        return arrayClassDef;
    }

    public static ClassDef getCommonSuperclass(ClassDef class1, ClassDef class2) {
        if (class1 == class2) {
            return class1;
        }

        if (class1 == null) {
            return class2;
        }

        if (class2 == null) {
            return class1;
        }

        //TODO: do we want to handle primitive types here? I don't think so.. (if not, add assert)

        if (class2.isInterface) {
            if (class1.implementsInterface(class2)) {
                return class2;
            }
            return theClassPath.javaLangObjectClassDef;
        }

        if (class1.isInterface) {
            if (class2.implementsInterface(class1)) {
                return class1;
            }
            return theClassPath.javaLangObjectClassDef;
        }

        if (class1 instanceof ArrayClassDef && class2 instanceof ArrayClassDef) {
            return getCommonArraySuperclass((ArrayClassDef)class1, (ArrayClassDef)class2);
        }

        //we've got two non-array reference types. Find the class depth of each, and then move up the longer one
        //so that both classes are at the same class depth, and then move each class up until they match

        //we don't strictly need to keep track of the class depth separately, but it's probably slightly faster
        //to do so, rather than calling getClassDepth() many times
        int class1Depth = class1.getClassDepth();
        int class2Depth = class2.getClassDepth();

        while (class1Depth > class2Depth) {
            class1 = class1.superclass;
            class1Depth--;
        }

        while (class2Depth > class1Depth) {
            class2 = class2.superclass;
            class2Depth--;
        }

        while (class1Depth > 0) {
            if (class1 == class2) {
                return class1;
            }
            class1 = class1.superclass;
            class1Depth--;
            class2 = class2.superclass;
            class2Depth--;
        }

        return class1;
    }

    private static ClassDef getCommonArraySuperclass(ArrayClassDef class1, ArrayClassDef class2) {
        assert class1 != class2;

        //If one of the arrays is a primitive array, then the only option is to return java.lang.Object
        //TODO: might it be possible to merge something like int[] and short[] into int[]? (I don't think so..)
        if (class1.elementClass instanceof PrimitiveClassDef || class2.elementClass instanceof PrimitiveClassDef) {
            return theClassPath.javaLangObjectClassDef;
        }

        //if the two arrays have the same number of dimensions, then we should return an array class with the
        //same number of dimensions, for the common superclass of the 2 element classes
        if (class1.arrayDimensions == class2.arrayDimensions) {
            ClassDef commonElementClass;
            if (class1.elementClass instanceof UnresolvedClassDef ||
                class2.elementClass instanceof UnresolvedClassDef) {
                commonElementClass = ClassPath.getUnresolvedObjectClassDef();
            } else {
                commonElementClass = getCommonSuperclass(class1.elementClass, class2.elementClass);
            }
            return getArrayClassDefByElementClassAndDimension(commonElementClass, class1.arrayDimensions);
        }

        //something like String[][][] and String[][] should be merged to Object[][]
        //this also holds when the element classes aren't the same (but are both reference types)
        int dimensions = Math.min(class1.arrayDimensions, class2.arrayDimensions);
        return getArrayClassDefByElementClassAndDimension(theClassPath.javaLangObjectClassDef, dimensions);
    }

    public static class ArrayClassDef extends ClassDef {
        private final ClassDef elementClass;
        private final int arrayDimensions;

        protected ArrayClassDef(String arrayClassType) {
            super(arrayClassType, ClassDef.ArrayClassDef);
            assert arrayClassType.charAt(0) == '[';

            int i=0;
            while (arrayClassType.charAt(i) == '[') i++;

            String elementClassType = arrayClassType.substring(i);

            if (i>256) {
                throw new ExceptionWithContext("Error while creating array class for element type " + elementClassType +
                        " with " + i + " dimensions. The maximum number of dimensions is 256");
            }

            try {
                elementClass = ClassPath.getClassDef(arrayClassType.substring(i));
            } catch (Exception ex) {
                throw ExceptionWithContext.withContext(ex, "Error while creating array class " + arrayClassType);
            }
            arrayDimensions = i;
        }

        /**
         * Returns the "base" element class of the array.
         *
         * For example, for a multi-dimensional array of strings ([[Ljava/lang/String;), this method would return
         * Ljava/lang/String;
         * @return the "base" element class of the array
         */
        public ClassDef getBaseElementClass() {
            return elementClass;
        }

        /**
         * Returns the "immediate" element class of the array.
         *
         * For example, for a multi-dimensional array of stings with 2 dimensions ([[Ljava/lang/String;), this method
         * would return [Ljava/lang/String;
         * @return the immediate element class of the array
         */
        public ClassDef getImmediateElementClass() {
            if (arrayDimensions == 1) {
                return elementClass;
            }
            return getArrayClassDefByElementClassAndDimension(elementClass, arrayDimensions - 1);
        }

        public int getArrayDimensions() {
            return arrayDimensions;
        }

        @Override
        public boolean extendsClass(ClassDef superclassDef) {
            if (!(superclassDef instanceof ArrayClassDef)) {
                if (superclassDef == ClassPath.theClassPath.javaLangObjectClassDef) {
                    return true;
                } else if (superclassDef.isInterface) {
                    return this.implementsInterface(superclassDef);
                }
                return false;
            }

            ArrayClassDef arraySuperclassDef = (ArrayClassDef)superclassDef;
            if (this.arrayDimensions == arraySuperclassDef.arrayDimensions) {
                ClassDef baseElementClass = arraySuperclassDef.getBaseElementClass();

                if (baseElementClass.isInterface) {
                    return true;
                }

                return baseElementClass.extendsClass(arraySuperclassDef.getBaseElementClass());
            } else if (this.arrayDimensions > arraySuperclassDef.arrayDimensions) {
                ClassDef baseElementClass = arraySuperclassDef.getBaseElementClass();
                if (baseElementClass.isInterface) {
                    return true;
                }

                if (baseElementClass == ClassPath.theClassPath.javaLangObjectClassDef) {
                    return true;
                }
                return false;
            }
            return false;
        }
    }

    public static class PrimitiveClassDef extends ClassDef {
        protected PrimitiveClassDef(String primitiveClassType) {
            super(primitiveClassType, ClassDef.PrimitiveClassDef);
            assert primitiveClassType.charAt(0) != 'L' && primitiveClassType.charAt(0) != '[';
        }
    }

    public static class UnresolvedClassDef extends ClassDef {
        protected UnresolvedClassDef(String unresolvedClassDef) {
            super(unresolvedClassDef, ClassDef.UnresolvedClassDef);
            assert unresolvedClassDef.charAt(0) == 'L';
        }

        protected ValidationException unresolvedValidationException() {
            return new ValidationException(String.format("class %s cannot be resolved.", this.getClassType()));
        }

        public ClassDef getSuperclass() {
            return theClassPath.javaLangObjectClassDef;
        }

        public int getClassDepth() {
            throw unresolvedValidationException();
        }

        public boolean isInterface() {
            throw unresolvedValidationException();
        }

         public boolean extendsClass(ClassDef superclassDef) {
            if (superclassDef != theClassPath.javaLangObjectClassDef && superclassDef != this) {
                throw unresolvedValidationException();
            }
            return true;
        }

        public boolean implementsInterface(ClassDef interfaceDef) {
            throw unresolvedValidationException();
        }

        public boolean hasVirtualMethod(String method) {
            if (!super.hasVirtualMethod(method)) {
                throw unresolvedValidationException();
            }
            return true;
        }
    }

    public static class FieldDef {
        public final String definingClass;
        public final String name;
        public final String type;

        public FieldDef(String definingClass, String name, String type) {
            this.definingClass = definingClass;
            this.name = name;
            this.type = type;
        }
    }

    public static class ClassDef implements Comparable<ClassDef> {
        private final String classType;
        private final ClassDef superclass;
        /**
         * This is a list of all of the interfaces that a class implements, either directly or indirectly. It includes
         * all interfaces implemented by the superclass, and all super-interfaces of any implemented interface. The
         * intention is to make it easier to determine whether the class implements a given interface or not.
         */
        private final TreeSet<ClassDef> implementedInterfaces;

        private final boolean isInterface;

        private final int classDepth;

        // classes can only be public or package-private. Internally, any private/protected inner class is actually
        // package-private.
        private final boolean isPublic;

        private final VirtualMethod[] vtable;

        //this maps a method name of the form method(III)Ljava/lang/String; to an integer
        //If the value is non-negative, it is a vtable index
        //If it is -1, it is a non-static direct method,
        //If it is -2, it is a static method
        private final HashMap<String, Integer> methodLookup;

        private final SparseArray<FieldDef> instanceFields;

        public final static int ArrayClassDef = 0;
        public final static int PrimitiveClassDef = 1;
        public final static int UnresolvedClassDef = 2;

        private final static int DirectMethod = -1;
        private final static int StaticMethod = -2;

        /**
         * The following fields are used only during the initial loading of classes, and are set to null afterwards
         * TODO: free these
         */

        //This is only the virtual methods that this class declares itself.
        private VirtualMethod[] virtualMethods;
        //this is a list of all the interfaces that the class implements directory, or any super interfaces of those
        //interfaces. It is generated in such a way that it is ordered in the same way as dalvik's ClassObject.iftable,
        private LinkedHashMap<String, ClassDef> interfaceTable;

        /**
         * This constructor is used for the ArrayClassDef, PrimitiveClassDef and UnresolvedClassDef subclasses
         * @param classType the class type
         * @param classFlavor one of ArrayClassDef, PrimitiveClassDef or UnresolvedClassDef
         */
        protected ClassDef(String classType, int classFlavor) {
            if (classFlavor == ArrayClassDef) {
                assert classType.charAt(0) == '[';
                this.classType = classType;
                this.superclass = ClassPath.theClassPath.javaLangObjectClassDef;
                implementedInterfaces = new TreeSet<ClassDef>();
                implementedInterfaces.add(ClassPath.getClassDef("Ljava/lang/Cloneable;"));
                implementedInterfaces.add(ClassPath.getClassDef("Ljava/io/Serializable;"));
                isInterface = false;
                isPublic = true;

                vtable = superclass.vtable;
                methodLookup = superclass.methodLookup;

                instanceFields = superclass.instanceFields;
                classDepth = 1; //1 off from java.lang.Object

                virtualMethods = null;
                interfaceTable = null;
            } else if (classFlavor == PrimitiveClassDef) {
                //primitive type
                assert classType.charAt(0) != '[' && classType.charAt(0) != 'L';

                this.classType = classType;
                this.superclass = null;
                implementedInterfaces = null;
                isInterface = false;
                isPublic = true;
                vtable = null;
                methodLookup = null;
                instanceFields = null;
                classDepth = 0; //TODO: maybe use -1 to indicate not applicable?

                virtualMethods = null;
                interfaceTable = null;
            } else /*if (classFlavor == UnresolvedClassDef)*/ {
                assert classType.charAt(0) == 'L';
                this.classType = classType;
                this.superclass = ClassPath.getClassDef("Ljava/lang/Object;");
                implementedInterfaces = new TreeSet<ClassDef>();
                isInterface = false;
                isPublic = true;

                vtable = superclass.vtable;
                methodLookup = superclass.methodLookup;

                instanceFields = superclass.instanceFields;
                classDepth = 1; //1 off from java.lang.Object

                virtualMethods = null;
                interfaceTable = null;
            }
        }

        protected ClassDef(UnresolvedClassInfo classInfo)  {
            classType = classInfo.classType;
            isPublic = classInfo.isPublic;
            isInterface = classInfo.isInterface;

            superclass = loadSuperclass(classInfo);
            if (superclass == null) {
                classDepth = 0;
            } else {
                classDepth = superclass.classDepth + 1;
            }

            implementedInterfaces = loadAllImplementedInterfaces(classInfo);

            //TODO: we can probably get away with only creating the interface table for interface types
            interfaceTable = loadInterfaceTable(classInfo);
            virtualMethods = classInfo.virtualMethods;
            vtable = loadVtable(classInfo);

            int directMethodCount = 0;
            if (classInfo.directMethods != null) {
                directMethodCount = classInfo.directMethods.length;
            }
            methodLookup = new HashMap<String, Integer>((int)Math.ceil(((vtable.length + directMethodCount)/ .7f)), .75f);
            for (int i=0; i<vtable.length; i++) {
                methodLookup.put(vtable[i].method, i);
            }
            if (directMethodCount > 0) {
                for (int i=0; i<classInfo.directMethods.length; i++) {
                    if (classInfo.staticMethods[i]) {
                        methodLookup.put(classInfo.directMethods[i], StaticMethod);
                    } else {
                        methodLookup.put(classInfo.directMethods[i], DirectMethod);
                    }
                }
            }

            instanceFields = loadFields(classInfo);
        }

        public String getClassType() {
            return classType;
        }

        public ClassDef getSuperclass() {
            return superclass;
        }

        public int getClassDepth() {
            return classDepth;
        }

        public boolean isInterface() {
            return this.isInterface;
        }

        public boolean isPublic() {
            return this.isPublic;
        }

        public boolean extendsClass(ClassDef superclassDef) {
            if (superclassDef == null) {
                return false;
            }

            if (this == superclassDef) {
                return true;
            }

            if (superclassDef instanceof UnresolvedClassDef) {
                throw ((UnresolvedClassDef)superclassDef).unresolvedValidationException();
            }

            int superclassDepth = superclassDef.classDepth;
            ClassDef ancestor = this;
            while (ancestor.classDepth > superclassDepth) {
                ancestor = ancestor.getSuperclass();
            }

            return ancestor == superclassDef;
        }

        /**
         * Returns true if this class implements the given interface. This searches the interfaces that this class
         * directly implements, any interface implemented by this class's superclasses, and any super-interface of
         * any of these interfaces.
         * @param interfaceDef the interface
         * @return true if this class implements the given interface
         */
        public boolean implementsInterface(ClassDef interfaceDef) {
            assert !(interfaceDef instanceof UnresolvedClassDef);
            return implementedInterfaces.contains(interfaceDef);
        }

        public boolean hasVirtualMethod(String method) {
            Integer val = methodLookup.get(method);
            if (val == null || val < 0) {
                return false;
            }
            return true;
        }

        public int getMethodType(String method) {
            Integer val = methodLookup.get(method);
            if (val == null) {
                return -1;
            }
            if (val >= 0) {
                return DeodexUtil.Virtual;
            }
            if (val == DirectMethod) {
                return DeodexUtil.Direct;
            }
            if (val == StaticMethod) {
                return DeodexUtil.Static;
            }
            throw new RuntimeException("Unexpected method type");
        }

        public FieldDef getInstanceField(int fieldOffset) {
            return this.instanceFields.get(fieldOffset, null);
        }

        public String getVirtualMethod(int vtableIndex) {
            if (vtableIndex < 0 || vtableIndex >= vtable.length) {
                return null;
            }
            return this.vtable[vtableIndex].method;
        }

        private void swap(byte[] fieldTypes, FieldDef[] fields, int position1, int position2) {
            byte tempType = fieldTypes[position1];
            fieldTypes[position1] = fieldTypes[position2];
            fieldTypes[position2] = tempType;

            FieldDef tempField = fields[position1];
            fields[position1] = fields[position2];
            fields[position2] = tempField;
        }

        private ClassDef loadSuperclass(UnresolvedClassInfo classInfo) {
            if (classInfo.classType.equals("Ljava/lang/Object;")) {
                if (classInfo.superclassType != null) {
                    throw new ExceptionWithContext("Invalid superclass " +
                            classInfo.superclassType + " for Ljava/lang/Object;. " +
                            "The Object class cannot have a superclass");
                }
                return null;
            } else {
                String superclassType = classInfo.superclassType;
                if (superclassType == null) {
                    throw new ExceptionWithContext(classInfo.classType + " has no superclass");
                }

                ClassDef superclass;
                try {
                    superclass = ClassPath.getClassDef(superclassType);
                } catch (Exception ex) {
                    throw ExceptionWithContext.withContext(ex,
                            String.format("Could not find superclass %s", superclassType));
                }

                if (!isInterface && superclass.isInterface) {
                    throw new ValidationException("Class " + classType + " has the interface " + superclass.classType +
                            " as its superclass");
                }
                if (isInterface && !superclass.isInterface && superclass !=
                        ClassPath.theClassPath.javaLangObjectClassDef) {
                    throw new ValidationException("Interface " + classType + " has the non-interface class " +
                            superclass.classType + " as its superclass");
                }

                return superclass;
            }
        }

        private TreeSet<ClassDef> loadAllImplementedInterfaces(UnresolvedClassInfo classInfo) {
            assert classType != null;
            assert classType.equals("Ljava/lang/Object;") || superclass != null;
            assert classInfo != null;

            TreeSet<ClassDef> implementedInterfaceSet = new TreeSet<ClassDef>();

            if (superclass != null) {
                for (ClassDef interfaceDef: superclass.implementedInterfaces) {
                    implementedInterfaceSet.add(interfaceDef);
                }
            }

            if (classInfo.interfaces != null) {
                for (String interfaceType: classInfo.interfaces) {
                    ClassDef interfaceDef;
                    try {
                        interfaceDef = ClassPath.getClassDef(interfaceType);
                    } catch (Exception ex) {
                        throw ExceptionWithContext.withContext(ex,
                                String.format("Could not find interface %s", interfaceType));
                    }
                    assert interfaceDef.isInterface();
                    implementedInterfaceSet.add(interfaceDef);

                    interfaceDef = interfaceDef.getSuperclass();
                    while (!interfaceDef.getClassType().equals("Ljava/lang/Object;")) {
                        assert interfaceDef.isInterface();
                        implementedInterfaceSet.add(interfaceDef);
                        interfaceDef = interfaceDef.getSuperclass();
                    }
                }
            }

            return implementedInterfaceSet;
        }

        private LinkedHashMap<String, ClassDef> loadInterfaceTable(UnresolvedClassInfo classInfo) {
            if (classInfo.interfaces == null) {
                return null;
            }

            LinkedHashMap<String, ClassDef> interfaceTable = new LinkedHashMap<String, ClassDef>();

            for (String interfaceType: classInfo.interfaces) {
                if (!interfaceTable.containsKey(interfaceType)) {
                    ClassDef interfaceDef;
                    try {
                        interfaceDef = ClassPath.getClassDef(interfaceType);
                    } catch (Exception ex) {
                        throw ExceptionWithContext.withContext(ex,
                                String.format("Could not find interface %s", interfaceType));
                    }
                    interfaceTable.put(interfaceType, interfaceDef);

                    if (interfaceDef.interfaceTable != null) {
                        for (ClassDef superInterface: interfaceDef.interfaceTable.values()) {
                            if (!interfaceTable.containsKey(superInterface.classType)) {
                                interfaceTable.put(superInterface.classType, superInterface);
                            }
                        }
                    }
                }
            }

            return interfaceTable;
        }

        //TODO: check the case when we have a package private method that overrides an interface method
        private VirtualMethod[] loadVtable(UnresolvedClassInfo classInfo) {
            //TODO: it might be useful to keep track of which class's implementation is used for each virtual method. In other words, associate the implementing class type with each vtable entry
            List<VirtualMethod> virtualMethodList = new LinkedList<VirtualMethod>();

            //copy the virtual methods from the superclass
            int methodIndex = 0;
            if (superclass != null) {
                for (int i=0; i<superclass.vtable.length; i++) {
                    virtualMethodList.add(superclass.vtable[i]);
                }

                assert superclass.instanceFields != null;
            }

            //iterate over the virtual methods in the current class, and only add them when we don't already have the
            //method (i.e. if it was implemented by the superclass)
            if (!this.isInterface) {
                if (classInfo.virtualMethods != null) {
                    addToVtable(classInfo.virtualMethods, virtualMethodList);
                }

                if (interfaceTable != null) {
                    for (ClassDef interfaceDef: interfaceTable.values()) {
                        if (interfaceDef.virtualMethods == null) {
                            continue;
                        }

                        addToVtable(interfaceDef.virtualMethods, virtualMethodList);
                    }
                }
            }

            VirtualMethod[] vtable = new VirtualMethod[virtualMethodList.size()];
            for (int i=0; i<virtualMethodList.size(); i++) {
                vtable[i] = virtualMethodList.get(i);
            }

            return vtable;
        }

        private void addToVtable(VirtualMethod[] localMethods, List<VirtualMethod> vtable) {
            for (VirtualMethod virtualMethod: localMethods) {
                boolean found = false;
                for (int i=0; i<vtable.size(); i++) {
                    VirtualMethod superMethod = vtable.get(i);
                    if (superMethod.method.equals(virtualMethod.method)) {
                        if (!ClassPath.theClassPath.checkPackagePrivateAccess || this.canAccess(superMethod)) {
                            found = true;
                            vtable.set(i, virtualMethod);
                            break;
                        }
                    }
                }
                if (!found) {
                    vtable.add(virtualMethod);
                }
            }
        }

        private boolean canAccess(VirtualMethod virtualMethod) {
            if (!virtualMethod.isPackagePrivate) {
                return true;
            }

            String otherPackage = getPackage(virtualMethod.containingClass);
            String ourPackage = getPackage(this.classType);
            return otherPackage.equals(ourPackage);
        }

        private String getPackage(String classType) {
            int lastSlash = classType.lastIndexOf('/');
            if (lastSlash < 0) {
                return "";
            }
            return classType.substring(1, lastSlash);
        }

        private int getNextFieldOffset() {
            if (instanceFields == null || instanceFields.size() == 0) {
                return 8;
            }

            int lastItemIndex = instanceFields.size()-1;
            int fieldOffset = instanceFields.keyAt(lastItemIndex);
            FieldDef lastField = instanceFields.valueAt(lastItemIndex);

            switch (lastField.type.charAt(0)) {
                case 'J':
                case 'D':
                    return fieldOffset + 8;
                default:
                    return fieldOffset + 4;
            }
        }

        private SparseArray<FieldDef> loadFields(UnresolvedClassInfo classInfo) {
            //This is a bit of an "involved" operation. We need to follow the same algorithm that dalvik uses to
            //arrange fields, so that we end up with the same field offsets (which is needed for deodexing).
            //See mydroid/dalvik/vm/oo/Class.c - computeFieldOffsets()

            final byte REFERENCE = 0;
            final byte WIDE = 1;
            final byte OTHER = 2;

            FieldDef[] fields = null;
            //the "type" for each field in fields. 0=reference,1=wide,2=other
            byte[] fieldTypes = null;

            if (classInfo.instanceFields != null) {
                fields = new FieldDef[classInfo.instanceFields.length];
                fieldTypes = new byte[fields.length];

                for (int i=0; i<fields.length; i++) {
                    String[] fieldInfo = classInfo.instanceFields[i];

                    String fieldName = fieldInfo[0];
                    String fieldType = fieldInfo[1];

                    fieldTypes[i] = getFieldType(fieldType);
                    fields[i] = new FieldDef(classInfo.classType, fieldName, fieldType);
                }
            }

            if (fields == null) {
                fields = new FieldDef[0];
                fieldTypes = new byte[0];
            }

            //The first operation is to move all of the reference fields to the front. To do this, find the first
            //non-reference field, then find the last reference field, swap them and repeat
            int back = fields.length - 1;
            int front;
            for (front = 0; front<fields.length; front++) {
                if (fieldTypes[front] != REFERENCE) {
                    while (back > front) {
                        if (fieldTypes[back] == REFERENCE) {
                            swap(fieldTypes, fields, front, back--);
                            break;
                        }
                        back--;
                    }
                }

                if (fieldTypes[front] != REFERENCE) {
                    break;
                }
            }

            int startFieldOffset = 8;
            if (this.superclass != null) {
                startFieldOffset = this.superclass.getNextFieldOffset();
            }

            int fieldIndexMod;
            if ((startFieldOffset % 8) == 0) {
                fieldIndexMod = 0;
            } else {
                fieldIndexMod = 1;
            }

            //next, we need to group all the wide fields after the reference fields. But the wide fields have to be
            //8-byte aligned. If we're on an odd field index, we need to insert a 32-bit field. If the next field
            //is already a 32-bit field, use that. Otherwise, find the first 32-bit field from the end and swap it in.
            //If there are no 32-bit fields, do nothing for now. We'll add padding when calculating the field offsets
            if (front < fields.length && (front % 2) != fieldIndexMod) {
                if (fieldTypes[front] == WIDE) {
                    //we need to swap in a 32-bit field, so the wide fields will be correctly aligned
                    back = fields.length - 1;
                    while (back > front) {
                        if (fieldTypes[back] == OTHER) {
                            swap(fieldTypes, fields, front++, back);
                            break;
                        }
                        back--;
                    }
                } else {
                    //there's already a 32-bit field here that we can use
                    front++;
                }
            }

            //do the swap thing for wide fields
            back = fields.length - 1;
            for (; front<fields.length; front++) {
                if (fieldTypes[front] != WIDE) {
                    while (back > front) {
                        if (fieldTypes[back] == WIDE) {
                            swap(fieldTypes, fields, front, back--);
                            break;
                        }
                        back--;
                    }
                }

                if (fieldTypes[front] != WIDE) {
                    break;
                }
            }

            int superFieldCount = 0;
            if (superclass != null) {
                superFieldCount = superclass.instanceFields.size();
            }

            //now the fields are in the correct order. Add them to the SparseArray and lookup, and calculate the offsets
            int totalFieldCount = superFieldCount + fields.length;
            SparseArray<FieldDef> instanceFields = new SparseArray<FieldDef>(totalFieldCount);

            int fieldOffset;

            if (superclass != null && superFieldCount > 0) {
                for (int i=0; i<superFieldCount; i++) {
                    instanceFields.append(superclass.instanceFields.keyAt(i), superclass.instanceFields.valueAt(i));
                }

                fieldOffset = instanceFields.keyAt(superFieldCount-1);

                FieldDef lastSuperField = superclass.instanceFields.valueAt(superFieldCount-1);
                char fieldType = lastSuperField.type.charAt(0);
                if (fieldType == 'J' || fieldType == 'D') {
                    fieldOffset += 8;
                } else {
                    fieldOffset += 4;
                }
            } else {
                //the field values start at 8 bytes into the DataObject dalvik structure
                fieldOffset = 8;
            }

            boolean gotDouble = false;
            for (int i=0; i<fields.length; i++) {
                FieldDef field = fields[i];

                //add padding to align the wide fields, if needed
                if (fieldTypes[i] == WIDE && !gotDouble) {
                    if (!gotDouble) {
                        if (fieldOffset % 8 != 0) {
                            assert fieldOffset % 8 == 4;
                            fieldOffset += 4;
                        }
                        gotDouble = true;
                    }
                }

                instanceFields.append(fieldOffset, field);
                if (fieldTypes[i] == WIDE) {
                    fieldOffset += 8;
                } else {
                    fieldOffset += 4;
                }
            }
            return instanceFields;
        }

        private byte getFieldType(String fieldType) {
            switch (fieldType.charAt(0)) {
                case '[':
                case 'L':
                    return 0; //REFERENCE
                case 'J':
                case 'D':
                    return 1; //WIDE
                default:
                    return 2; //OTHER
            }
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (!(o instanceof ClassDef)) return false;

            ClassDef classDef = (ClassDef) o;

            return classType.equals(classDef.classType);
        }

        @Override
        public int hashCode() {
            return classType.hashCode();
        }

        public int compareTo(ClassDef classDef) {
            return classType.compareTo(classDef.classType);
        }
    }

    private static class VirtualMethod {
        public String containingClass;
        public String method;
        public boolean isPackagePrivate;
    }

    /**
     * This aggregates the basic information about a class in an easy-to-use format, without requiring references
     * to any other class.
     */
    private static class UnresolvedClassInfo {
        public final String dexFilePath;
        public final String classType;
        public final boolean isPublic;
        public final boolean isInterface;
        public final String superclassType;
        public final String[] interfaces;
        public final boolean[] staticMethods;
        public final String[] directMethods;
        public final VirtualMethod[] virtualMethods;
        public final String[][] instanceFields;

        public UnresolvedClassInfo(String dexFilePath, ClassDefItem classDefItem) {
            this.dexFilePath = dexFilePath;

            classType = classDefItem.getClassType().getTypeDescriptor();

            isPublic = (classDefItem.getAccessFlags() & AccessFlags.PUBLIC.getValue()) != 0;
            isInterface = (classDefItem.getAccessFlags() & AccessFlags.INTERFACE.getValue()) != 0;

            TypeIdItem superclassType = classDefItem.getSuperclass();
            if (superclassType == null) {
                this.superclassType = null;
            } else {
                this.superclassType = superclassType.getTypeDescriptor();
            }

            interfaces = loadInterfaces(classDefItem);

            ClassDataItem classDataItem = classDefItem.getClassData();
            if (classDataItem != null) {
                boolean[][] _staticMethods = new boolean[1][];
                directMethods = loadDirectMethods(classDataItem, _staticMethods);
                staticMethods = _staticMethods[0];
                virtualMethods = loadVirtualMethods(classDataItem);
                instanceFields = loadInstanceFields(classDataItem);
            } else {
                staticMethods = null;
                directMethods = null;
                virtualMethods = null;
                instanceFields = null;
            }
        }

        private String[] loadInterfaces(ClassDefItem classDefItem) {
            TypeListItem typeList = classDefItem.getInterfaces();
            if (typeList != null) {
                List<TypeIdItem> types = typeList.getTypes();
                if (types != null && types.size() > 0) {
                    String[] interfaces = new String[types.size()];
                    for (int i=0; i<interfaces.length; i++) {
                        interfaces[i] = types.get(i).getTypeDescriptor();
                    }
                    return interfaces;
                }
            }
            return null;
        }

        private String[] loadDirectMethods(ClassDataItem classDataItem, boolean[][] _staticMethods) {
            List<EncodedMethod> encodedMethods = classDataItem.getDirectMethods();
            if (encodedMethods.size() > 0) {
                boolean[] staticMethods = new boolean[encodedMethods.size()];
                String[] directMethods = new String[encodedMethods.size()];

                for (int i=0; i<encodedMethods.size(); i++) {
                    EncodedMethod encodedMethod = encodedMethods.get(i);

                    if ((encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) != 0) {
                        staticMethods[i] = true;
                    }
                    directMethods[i] = encodedMethod.method.getShortMethodString();
                }
                _staticMethods[0] = staticMethods;
                return directMethods;
            }
            return null;
        }

        private VirtualMethod[] loadVirtualMethods(ClassDataItem classDataItem) {
            List<EncodedMethod> encodedMethods = classDataItem.getVirtualMethods();
            if (encodedMethods.size() > 0) {
                VirtualMethod[] virtualMethods = new VirtualMethod[encodedMethods.size()];
                for (int i=0; i<encodedMethods.size(); i++) {
                    virtualMethods[i] = new VirtualMethod();
                    EncodedMethod encodedMethod = encodedMethods.get(i);

                    virtualMethods[i].isPackagePrivate = methodIsPackagePrivate(encodedMethod.accessFlags);
                    virtualMethods[i].containingClass = classDataItem.getParentType().getTypeDescriptor();
                    virtualMethods[i].method = encodedMethods.get(i).method.getShortMethodString();
                }
                return virtualMethods;
            }
            return null;
        }

        private static boolean methodIsPackagePrivate(int accessFlags) {
            return (accessFlags & (AccessFlags.PRIVATE.getValue() |
                                   AccessFlags.PROTECTED.getValue() |
                                   AccessFlags.PUBLIC.getValue())) == 0;
        }

        private String[][] loadInstanceFields(ClassDataItem classDataItem) {
            List<EncodedField> encodedFields = classDataItem.getInstanceFields();
            if (encodedFields.size() > 0) {
                String[][] instanceFields = new String[encodedFields.size()][2];
                for (int i=0; i<encodedFields.size(); i++) {
                    EncodedField encodedField = encodedFields.get(i);
                    instanceFields[i][0] = encodedField.field.getFieldName().getStringValue();
                    instanceFields[i][1] = encodedField.field.getFieldType().getTypeDescriptor();
                }
                return instanceFields;
            }
            return null;
        }
    }
}

redpajama_set_name: RedPajamaGithub


Inner Magazine (www.innermagazine.org) is an international peer-reviewed journal. The aim of the magazine is to investigate debate and reflect on the interior architecture in all its different aspects.
We are looking for contributors for next issue that will be published on December 2018.
In order to better organize the publication, a notification of interest before sending the complete paper is appreciated, but not obligatory.
Contributions should be written in English and include a 100-300 words abstract.


Toft Nook is a small stone detached barn on the Toft Estate sharing the courtyard with Toft Hall, Toft Barn and Chels Barn. Should you need to accommodate an extra couple of guests you can hire Toft Nook as an extra to your other chosen Party House. Alternatively some guests may choose to hire it to accommodate guests who perhaps want to go to bed early or prefer some extra privacy from the main party!
This annex comes with a bedroom with a comfortable double bed and a good size wardrobe. There's also a pull-out sofa bed in its cosy living room / kitchen. Here you'll also find a dining table, TV and a DVD player. There are lovely high ceilings with the original beams and a travertine stone floor with warm underfloor heating. The kitchen is equipped with a cooker, hob, kettle, sink, fridge, and has granite work surfaces and oak doors. The other door in this Peak District annex lead to a well fitted shower room.


We have an opening for an ADMIN ASST-HRLY (FULL-TIME) position.
Location: MSU - Panda Express - 1110 E Madison Ave., Springfield. MO 65807 Note: online applications accepted only.
Schedule: FT; Monday through Friday, 8:00am to 4:30pm, including a few weekend events throughout the year.
Requirement: Prior clerical or bookkeeping experience required.
This position is eligible for an Employee Referral Bonus! If you know someone that would be a great fit for this role, you can refer them to this position and potentially earn an Employee Referral Bonus! Click here to view the step-by-step instructions to refer a friend to this position.
Summary: Responsible for clerical functions and administrative support of food service programs.
Answer telephones and direct inquires in a professional and client centric manner.
Assist management staff in preparing confidential employment and labor relations documents, including but not limited to proposed disciplinary notices.
Assist with staffing, including finding staff when employees call out on short notice.
Work effectively and maintain good working relationships with co-workers, school personnel, administrators, student's parents and Supervisor.
Complete and maintain accurate and up to date records of students eligible for free and reduced priced lunches if applicable.
Enter weekly cash sales and meal counts using computer.
Perform daily bank deposit reconciliation.
Process vendor invoices for payment - using computer, making sure addition is correct and checking item prices against bid specifications, making sure there is no discrepancy in pricing.
Perform monthly vendor statement reconciliation.
Prepare monthly state claim form for reimbursement.
Assist in preparation of end of month financial reports.
Attend in-service and/or safety meetings as required.
Maintain clean and safe work environment; ability to perform job safely.


text:
Last 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
Astros = CHEATERS
138,693 Views | 1481 Replies | Last: 10 mo ago by Aggies2009
In reply to TheAngelFlight • 1:19p, 11/14/19
TheAngelFlight said:
mazag08 said:
Trust me Rangers
Take it to the rivalry thread. This thread wasn't started by a Rangers fan and half the people y'all have argued with aren't Rangers fans, either.
No, I'll say what I want and you can deal with it snowflake.
How will I possibly deal with such hard hitting stuff, though?
And you're going to throw out the snowflake card after declaring your and the Astros' victimhood? Okay...
Yes, because you cried and got your feelings hurt that I didnt refer to you by whatever craptastic team you follow.
ORAggieFan
In reply to 03_Aggie • 1:19p, 11/14/19
Thanks, I did watch that earlier and forgot. I actually put it off as I couldn't hear the sounds w/o him slowing it down like I could in the 2017 ones. I need to hear it in real time like the others before I trust it much.
That said, should it be proven as much as 2017, my inclination would be it is through technology. But, we don't have the evidence yet for 2019 like we have for 2017.
TheAngelFlight
In reply to mazag08 • 1:45p, 11/14/19
Don't you think I would have told what team I support if that was my point?
agsquirrel97
2:12p, 11/14/19
I self identify as an Astros fan and my pronouns are He/Him/His.
If there is evidence of electronic cheating by the Astros I would expect some sort of punishment comparable to precedented punishments. While I acknowledge that there was monitors in the hall in 2017, which was not illegal and I also acknowledge that Fiers has made an accusation, I do not believe you punish an alleged 2-year-old crime, prior to the MLB changes and proclamation, based on the word of a previous employee(s) because there is a different employee also on record saying Astro tactics were within the rules. If there is additional physical evidence of electronic surveillance, I am open to discussing it. I also need to disclose that I was very skeptical of Kristen Blasey-Ford's story, so take it for what it's worth.
The concern that I have is JomBoy states in his video, "This is happening so fast that it has to be done with a camera" and I have seen several similar claims here. I take issue with the proclamation that it HAS to be cheating. I don't think anyone is arguing that sign stealing is part of the "game inside the game" are we? That is as old as baseball. Just because you want something to be true, doesn't mean it is true. Just because I want it to be true that the Astros are playing inside the lines, doesn't make it so. If you can acknowledge my statement, then surely you can agree that just because you want it to be true that the Astros are cheating, doesn't make it so either, right?
This brings me to my point, there is an investigation and I think MLB has every desire to get it right, so I will wait for their evidence from a thorough investigation. I will not claim the Astros were not cheating, because I don't know.
In the meantime, I decided to look closer and see if my untrained eye could pick anything up on JomBoy's video. Mind you, I am no expert, but I approached this from the point of view of the dugout, is there anything Farquhar does that is visible to the dugout and not the batter? Is there anything that may actually be faster than a camera and monitor?
First, the catcher breaks the cardinal sign rule, keep your signs up and in your crotch, don't let them hang below your thighs, probably not stealable, but really bad technique for a pro.
Next, from JomBoy's video, here is when Farquhar comes to rest, every pitch as shown in the video (I hope in order, they are timestamped). My untrained eye sees what seems to be a loading up on the back leg for fast balls and a chicken wing right arm for off speed. Both of those characteristics would be very noticable from the dugout. Every offspeed pitch shows the "Bang" in the screenshot. I am not saying that is what the dugout was keying on, I am saying that is faster than a camera relayed to a monitor. There are plenty of tells and these two are not obvious to the batter perspective but very obvious to the dugout.
TexasRebel
In reply to agsquirrel97 • 2:18p, 11/14/19
Careful there. You're using an electronic device to remember.
Eso si, Que es
The guy in the long sleeve pink shirt in row 2 to the right is stealing the catchers signs, he is pointing it out to his wife multiple times - here comes the change up!
dugout was keying on Mr. Pink shirt.
Proposition Joe
Whether you believe it happened, don't believe it happened, believe it's significant or don't believe it's significant...
This idea that there isn't/wasn't enough "time" before the pitch to make a difference is only being said by people who don't know how quickly decisions are made by batters at that level.
Anytime before that arm actually starts moving forward that the batter hears an indication of the pitch type will be able to be used, predominantly in situations where he is looking fastball but gets notified to sit back an extra half-second to destroy an off-speed pitch.
In reply to Proposition Joe • 2:58p, 11/14/19
Proposition Joe said:
Just to be clear, I believe audible signals were being used by the Astros to transfer information to the batters.
I do not believe sign stealing and signaling is outside the lines and have no issue with those audible cues. In fact, during the season I am on record to saying that I wish we would do random audible cues to amp up our "game inside the game". I would like to see every batter getting on first base relaying something to the 1st base coach and him signal back to the dugout, just to make people wonder what do they have?
Using electronics to gain the information is outside the lines and should be punished, beating on a trash can is funny as F to me and in no way is cheating to use said trashcan to send morse code.
PlaneCrashGuy
agsquirrel97 said:
That's a pretty neat explanation, that only could explain the video, but it tackles none of the other evidence.
1) It doesn't explain the difference in stats for the time the accusations were levied, click on this tweet and read through the whole thread, its not just Altuve
2) Without seeing the dugout view we can't know how obvious his stance before the throw really looks.
3) If it was because he was tipping pitches to the dugout, why did the former player say they were cheating, instead of just telling the young guys to make sure they don't tip any pitches?
4) Why would the team not say the tips were being pitched by the dugout?
5) Occam's Razor
Like you said, until the investigation is finished we don't know- but there's nothing wrong with saying "this looks bad" and if it comes out they were cheating they should be punished.
And no one has an issue with the trash can part. Are we to believe the sources all lied about the TV while telling the truth about the bat and can?
The argument is now down to whether one believes the very logical account of multiple witnesses about the TV being used or whether they somehow stole signs another way, with no electronics and relayed that in real time to the tunnel.
Flexbone
In reply to PlaneCrashGuy • 3:11p, 11/14/19
lda6339 said:
Flexbone said:
ClickClack said:
Aggies2009 said:
Admittedly, there have been many more examples of it happening in 2017 than 2019. But it's happened in 2019. And there's this thing about trust that if you are a proven liar and cheater, people are going to think you're doing it even when you're not. Humans have evolved to feel this way.
Until then, everybody keep grasping at anything you can to make you feel better that the Astros won a WS and are more relevant than your team.
LOL 1 WS = more relevant lol
Here's this dumbass again. Relevance is, by its very nature, dependent upon time and is relative. The Cardinals aren't more relevant in Major League Baseball just because they won World Series titles a long time ago. The Astros have been the best team in the sport for the last 3 year period. They are the most relevant team in baseball over that period.
I challenge you to write one post to someone you disagree without attacking them in some way.
Your insults aside, if the Astros are the most relevant team is due to national press, the Astros would only maybe top that list on the back of negative media attention alone. That being said, winningest does not mean most relevant.
And why even bring the Cardinals up? No one said anything about them. Houston fans seem to have a huge little brother syndrome with the rest of the league
Yes, "relevance" as everyone here intends it to mean, INCLUDING YOU (who posted "LOL 1 WS - more relevant lol") a performance-based measure. Now you're trying to shift gears away from that into some nebulous, undefinable meaning so that you can somehow argue something different.
I'm bringing up the Cardinals because everyone here knows you're a Cardinals fan, as you've stated repeatedly while hanging out day and night on Astros post-season game threads hoping they'd lose. Little brother syndrome? Why would the Astros have little brother syndrome when they're the best team in baseball the last several years?
Aggies2009
In reply to ORAggieFan • 3:11p, 11/14/19
ORAggieFan said:
It's worth noting that there haven't been examples of banging on trash cans or whistles when they're on the road.
Only at home.
South Platte
Hopefully someone can address these questions:
1. Has anybody asked Gattis what was going on with the banging sound before he got the pitch? His answer might be telling or he might not even remember that at bat . . . Farquhar apparently has confirmed they noticed.
2. Is it possible that the Astros were just messing with the pitcher by banging on a trash can to make him think they were stealing signs? Shenanigans happen . . . although it's funny that a career power hitter was fouling balls off like he was Wade Boggs.
3. Why do we have a video of this random Gattis at bat in the first place?? There are 1000's of at bats during a year. Any other examples out there?
In reply to South Platte • 3:17p, 11/14/19
South Platte said:
1. I'm not sure.
2. It's possible. But there are many examples of a certain pattern. One knock being a curveball, two knocks being a changeup. That goes beyond "messing with a pitcher" and isn't a coincidence that knocks happen on offspeed pitches.
3. Tons.
In reply to Flexbone • 3:19p, 11/14/19
Can you name a relevance based stat the astros are #1 in other than number of WS wins 3 years ago or WS losses this year? Wins dont make a team relevant, the cowboys have been average and they're still top 3 or 5 relevant pro teams.
I'm not saying the cardinals are the most relevant, but it sure as **** aint the stros my guy. You gotta get out of houston sometime and see the world. Oh and I didnt bring up the WS- the post I was replying to did, but go off king.
In reply to Aggies2009 • 3:19p, 11/14/19
All what you WANT to believe.
1. Has anybody asked Gattis what was going on with the banging sound before he got the pitch? His answer might be telling or he might not even remember that at bat . . . Farquhar apparently has confirmed they noticed. No, which is telling.
2. Is it possible that the Astros were just messing with the pitcher by banging on a trash can to make him think they were stealing signs? Shenanigans happen . . . although it's funny that a career power hitter was fouling balls off like he was Wade Boggs. They had a damn good track record of only banging on it for off-speeds, so doubt it.
3. Why do we have a video of this random Gattis at bat in the first place?? There are 1000's of at bats during a year. Any other examples out there? Several
No, they're facts. Video backs up everything I said. Sorry that reality isn't on your side, bud. Obnoxious ****s like you are exactly why every MLB fan outside of Houston is loving the current scandal that at the very least taints the franchise. And why everyone is hoping the hammer comes down hard. Hope that helps.
If wins don't make a team "relevant"...why did you respond with a wins-based stat to dispute said relevance?
How stupid are you?
That's a very good point. If they were picking up signs by non technical means, they wouldn't be limited to only doing it at home.
Asked and answered LOL
Oh and I didnt bring up the WS- the post I was replying to did, but go off king.
No, they're facts. Video backs up everything I said. Sorry that reality isn't on your side, bud.
Video backs up your claim that the Astros were recognizing pitches before they were thrown? Ok. What about the use of electronic devices? Where is the support for that, champ?
Sorry your team sucks.
What's my team?
Again, multiple players saying it happened points that direction. The fact that it only happens at home says even more.
2018 World Champions - Boston Red Sox
2019 World Champions - Washington Nationals
Here are a bunch (click on tweet to see them all) including Beltran who has denied it so far.
If that's the case...then why didn't you simply reply with wins are the determination of "relevance"? Because at that time, you didn't expect someone to respond to you with the fact that the Astros are the best team over that period, and thus, you decided to shift the argument to a completely subjective, undefinable basis.
You haven't answered this question at all. You just keep deflecting, which is usually what people that are boxed in do. I should get out and see the world? I've lived in Texas, Florida, D.C., and New York. Where have you lived?
"Over the last several years." That means "during a time period spanning X" to those who have basic reading comprehension skills. Now, tell me, which of those teams have been better than the Astros OVER THE LAST 3 YEARS? The question calls for an answer in the collective. Do you need me to draw you a picture?
https://www.youtube.com/watch?v=QvwkaKHUNYw&feature=youtu.be&t=2574
No hits = Fast ball
One hit = Slider
Two hits = Changeup
How did nobody notice this before?
Where did he do this?
Do you think it's possible that the Rangers bens the rules? If they do, do you think anyone gives a *****
It's quoted above.
That's a great example and using a game posted by MLB account. I could close my eyes and know the pitch coming.
"LOL 1 WS = more relevant lol" is not using a wins-based stat to dispute who is more relevant. It is, rightly or wrongly, laughing at your use of a wins-based stat to dispute who is more relevant. Do you not know what "lol" means or something?
You have quite an obsession with the Rangers. I know that you're trying to reframe everything here away from the current scandal that completely ****s on everything the Astros accomplished, but the evidence is still there, no matter how much you insult other posters, the Rangers, the Yankees, the Cardinals, or whoever else. You've spent too much time on OR.
As I said earlier
Skip to Last Page 1 Page 2 Page 3 Page 4 Page 5 Page 6 Page 7 Page 8 Page 9 Page 10 Page 11 Page 12 Page 13 Page 14 Page 15 Page 16 Page 17 Page 18 Page 19 Page 20 Page 21 Page 22 Page 23 Page 24 Page 25 Page 26 Page 27 Page 28 Page 29 Page 30 Page 31 Page 32 Page 33 Page 34 Page 35 Page 36 Page 37 Page 38 Page 39 Page 40 Page 41 Page 42 Page 43
Page 9 of 43 ▼
Good Poster

redpajama_set_name: RedPajamaCommonCrawl


text:
Homeless more likely to die after heart attack
(HealthDay)—Homeless people are three times more likely to die after a heart attack than other patients, a new study finds.
"Our study shows a dramatically higher rate of mortality after heart attacks in people experiencing homelessness compared to non-homeless patients," said researcher Dr. Samantha Liauw of the University of Toronto. "More research is needed to discover the reasons for this disparity in outcomes so that the chances of survival can be improved in this vulnerable population."
Liauw and her colleagues compared more than 2,800 heart attack patients admitted to a Toronto hospital between 2008 and 2017. Of those, 75 were homeless.
Among homeless patients, 19% died in the hospital, compared with 6% of others. Homeless patients were younger than others and more likely to be men.
Eighty-four percent of homeless patients smoked compared to half of patients who were not homeless. Rates of high blood pressure, high cholesterol and diabetes were similar between the groups.
Also, more homeless patients suffered from mental conditions. They were more likely than others to abuse alcohol and drugs and were more likely to suffer a serious complication of heart attack called cardiogenic shock that occurs when the heart cannot supply enough blood and oxygen to the brain and other vital organs. They were more likely than other patients to go into cardiac arrest.
Both groups received medications, testing and stents, but the rate of stenting was lower in the homeless (80% versus 90% in non-homeless patients).
The findings were scheduled to be presented Wednesday at a virtual meeting of the 2020 Canadian Cardiovascular Congress.
"The elevated risk at a younger age could be related to chronic stress from being homeless, higher rates of smoking, poverty, and unreliable access to healthy food. Lack of trust in the medical system, poor access to health care for chronic conditions and slower receipt of emergency therapies may also have contributed," Liauw said in a news release from the European Society of Cardiology, which will participate in the meeting.
Although both patient groups received timely treatment, she suspects the symptom start time listed for homeless people may be inaccurate, resulting in a longer gap before therapy began.
"This illustrates that we need new methods to study this disadvantaged part of society," Liauw said.
Findings presented at meetings are considered preliminary until they're published in a peer-reviewed journal.
Homeless people receive less treatment in hospitals for heart attacks, have higher readmission rates
More information: For more on heart attack, visit the American Heart Association.
Citation: Homeless more likely to die after heart attack (2020, October 22) retrieved 20 January 2021 from https://medicalxpress.com/news/2020-10-homeless-die-heart.html
Homeless likelier to go on ventilators for respiratory infections than the non-homeless
Disparities in care among homeless adults hospitalized for cardiovascular conditions
Homeless patients are more likely to be readmitted to a hospital within 30 days
Homelessness tied to higher readmission rates
Homeless veterans at increased risk of hospital readmission after surgery


text:
package eu.hyvar.feature.mapping.resource.hymapping;

/**
 * <p>
 * A mapping from an identifier to an EObject.
 * </p>
 *
 * @param <ReferenceType> the type of the reference this mapping points to.
 */
public interface IHymappingElementMapping<ReferenceType> extends eu.hyvar.feature.mapping.resource.hymapping.IHymappingReferenceMapping<ReferenceType> {

	/**
	 * Returns the target object the identifier is mapped to.
	 */
	public ReferenceType getTargetElement();
}