<repo_name>johny1122/Java-OOP<file_sep>/Ex6/src/CheckScope.java
import java.util.HashMap;
import java.util.InvalidPropertiesFormatException;
import java.util.Stack;

/**
 * Checking the global scope and the methods scopes thoroughly
 */
public class CheckScope {
    private static final String ERROR_MESSAGE_GLOBAL = "ERROR: Global scope must contain methods and variable " +
            "declarations\\assignments only";
    private static final String ERROR_MESSAGE_NESTED_METHOD = "ERROR: Methods may only be declared at the global scope";
    private static final String OPEN_CURLY_BRACKET = "{";
    private static final String CLOSE_CURLY_BRACKET = "}";
    private static final String NEW_LINE = "\n";
    private static final String REGEX_EMPTY_LINE = "^\\s*$";
    private static final String REGEX_BRACKETS_DELIMITER = "(?<=[{}])|(?=[{}])";

    private static String[] methodParameterLines = null;
    private static HashMap<String, Method> methods;

    /**
     * Checking the scopes starting with the global scope and than the methods
     * @param code
     * @throws InvalidPropertiesFormatException
     */
    public static void checkScopes(String code) throws InvalidPropertiesFormatException {
        methods = CheckMethod.findMethods(code);
        String globalScopeCode = getGlobalScopeCode(code);
        Scope globalScope = checkGlobalScopeLines(globalScopeCode);

        checkMethods(globalScope);
    }

    /**
     * Getting the global scope code by deleting the methods from it
     * @param code
     * @return
     */
    private static String getGlobalScopeCode(String code){
        for(Method method: methods.values()){
            code = code.replace(method.getCode(), "");
        }

        return code;
    }

    /**
     * Checking the methods scope (and any scope beneath them)
     * @param globalScope
     * @throws InvalidPropertiesFormatException
     */
    private static void checkMethods(Scope globalScope) throws InvalidPropertiesFormatException {
        methodParameterLines = null;

        for(Method method: methods.values()){
            String[] splitCode = method.getCode().split(REGEX_BRACKETS_DELIMITER);
            scopify(splitCode, globalScope);
            setUninitializedGlobal(globalScope);
        }
    }

    /**
     * After checking each method we need to set the globally uninitialized global variables for the next method
     * @param globalScope
     */
    private static void setUninitializedGlobal(Scope globalScope){
        for(Variable variable: globalScope.getScopeVariables().values()){
            if(!variable.isGlobalInitialized()){
                variable.setUnInitialized();
            }
        }
    }

    /**
     * Going over the scopes inside the method and checking all lines validity and updating variables
     * @param splitCode
     * @param globalScope
     * @throws InvalidPropertiesFormatException
     */
    private static void scopify(String[] splitCode, Scope globalScope) throws InvalidPropertiesFormatException {
        Stack<Scope> scopeStack = new Stack<>();
        scopeStack.push(globalScope);
        String prevBracket = OPEN_CURLY_BRACKET;
        int currIndex = 0;
        Scope newScope;

        while(currIndex < splitCode.length){
            String currCode = splitCode[currIndex];

            if(isBracket(currCode)){
                prevBracket = currCode;
            }
            else{
                if(prevBracket.equals(OPEN_CURLY_BRACKET)){
                    newScope = new Scope(scopeStack.peek());
                    checkMethodLines(currCode + splitCode[currIndex + 1], newScope, globalScope);
                    scopeStack.push(newScope);
                }
                else{
                    scopeStack.pop();
                    Scope currScope = scopeStack.peek();

                    if(currScope != globalScope && currIndex + 1 < splitCode.length) {
                        checkMethodLines(currCode + splitCode[currIndex + 1], currScope, globalScope);
                    }
                }
            }

            currIndex++;
        }
    }

    /**
     * Is bracket "}" or "{"
     * @param str
     * @return
     */
    private static boolean isBracket(String str){
        return str.equals(OPEN_CURLY_BRACKET) || str.equals(CLOSE_CURLY_BRACKET);
    }

    /**
     * Checking the global scope - must have variable related code only (after removing the methods code)
     * and updating the global variables
     * @param code
     * @return
     * @throws InvalidPropertiesFormatException
     */
    private static Scope checkGlobalScopeLines(String code) throws InvalidPropertiesFormatException {
        String[] lines = code.split("\n");
        Scope globalScope = new Scope(null);

        for(String line: lines) {
            if(line.matches(REGEX_EMPTY_LINE)){
                continue;
            }
            else if(CheckVariable.checkJustFormat(line)){
                CheckVariable.checkVariableLine(line, globalScope, true);
            }
            else{
                throw new InvalidPropertiesFormatException(ERROR_MESSAGE_GLOBAL);
            }
        }

        return globalScope;
    }

    /**
     * Given a scope's portion of a code, we check each line for more advanced errors (not syntax)
     * @param code
     * @param scope
     * @param globalScope
     * @throws InvalidPropertiesFormatException
     */
    private static void checkMethodLines(String code, Scope scope, Scope globalScope)
            throws InvalidPropertiesFormatException {
        String[] lines = code.split(NEW_LINE);

        if(methodParameterLines != null){
            for(String line: methodParameterLines) {
                CheckVariable.checkVariableLine(line, scope, true);
            }

            for(Variable variable: scope.getScopeVariables().values()){
                variable.setInitialized();
            }

            methodParameterLines = null;
        }

        for(String line: lines) {
            if(line.matches(CheckMethod.REGEX_RETURN) ||
                    line.matches(CheckMethod.REGEX_CLOSE_CURLY_BRACKET) ||
                    line.matches(REGEX_EMPTY_LINE)){
                continue;
            }
            else if(CheckIfWhile.checkJustFormat(line)){
                CheckIfWhile.checkIfWhileLine(line, scope);
            }
            else if(CheckMethod.isMethodSignatureLayout(line)){
                if(scope.getParentScope() == globalScope) // Methods only on global scope
                {
                    methodParameterLines = CheckMethod.getParameterVariablesLines(line);
                }
                else{
                    throw new InvalidPropertiesFormatException(ERROR_MESSAGE_NESTED_METHOD);
                }
            }
            else if(CheckMethodCall.isValidMethodCallLayout(line)){
                CheckMethodCall.checkMethodCall(CheckMethodCall.getMethodCall(line), methods, scope);
            }
            else {
                CheckVariable.checkVariableLine(line, scope, true);
            }
        }
    }
}
<file_sep>/Ex3/src/BoopingSite.java
import oop.ex3.searchengine.Hotel;
import oop.ex3.searchengine.HotelDataset;

import java.util.*;


public class BoopingSite {


	/** representing double max latitude valid value of 90 */
	private static final double MAX_LATITUDE_VALID = 90.0;

	/** representing double max longitude valid value of 180 */
	private static final double MAX_LONGITUDE_VALID = 180.0;


	private final ArrayList<Hotel> hotels = new ArrayList<Hotel>();

	/**
	 * constructor of BoopingSite
	 * @param name: string of the name of the dataset
	 */
	public BoopingSite(String name) {
		Hotel[] array_hotels = HotelDataset.getHotels(name);
		hotels.addAll(Arrays.asList(array_hotels));
	}


	/**
	 * return an ArrayList of all the hotels in the database which located in the given valid city
	 * @param city: String of valid city name in the database
	 * @return ArrayList of all hotels in the given city
	 */
	private ArrayList<Hotel> allHotelsInCity(String city) {
		ArrayList<Hotel> hotelsInCity = new ArrayList<Hotel>();

		// filter for all the hotels in the given city
		for (Hotel hotel : hotels) {
			if (hotel.getCity().equals(city)) {
				hotelsInCity.add(hotel);
			}
		}
		return hotelsInCity;
	}


	/**
	 * returns an Hotel array located in the given city sorted from the highest star rating to the lowest. if
	 * two hotels have the same rating it will sort the two hotels according to the alphabet order of the
	 * property name.
	 * @param city: String of the city
	 * @return: sorted hotel array by rating in the given city
	 */
	public Hotel[] getHotelsInCityByRating(String city) {
		ArrayList<Hotel> hotelsInCity = new ArrayList<Hotel>();

		// city name is null
		if (city == null) {
			return hotelsInCity.toArray(new Hotel[0]);
		}

		hotelsInCity = allHotelsInCity(city);

		RatingCompare ratingCompare = new RatingCompare();
		Collections.sort(hotelsInCity, ratingCompare);
		Collections.reverse(hotelsInCity);

		return hotelsInCity.toArray(new Hotel[0]);
	}


	/**
	 * returns an Hotel array sorted by proximity from the given location in ascending order. if two hotels
	 * have the same proximity it will sort the two hotels according to the number of points-of-interest they
	 * are close to.
	 * @param latitude: given latitude
	 * @param longitude: given longitude
	 * @return: sorted hotel array by proximity
	 */
	public Hotel[] getHotelsByProximity(double latitude, double longitude) {
		ArrayList<Hotel> hotelsProximity = new ArrayList<Hotel>();

		// latitude or longitude are not valid
		if ((Math.abs(latitude) > MAX_LATITUDE_VALID) || (Math.abs(longitude) > MAX_LONGITUDE_VALID)) {
			return hotelsProximity.toArray(new Hotel[0]);
		}

		hotelsProximity = hotels;

		ProximityCompare proximityCompare = new ProximityCompare(latitude, longitude);
		Collections.sort(hotelsProximity, proximityCompare);

		return hotelsProximity.toArray(new Hotel[0]);
	}


	/**
	 * returns an Hotel array sorted by proximity from the given location in ascending order in the given
	 * city. if two hotels have the same proximity it will sort the two hotels according to the number of
	 * points-of-interest they are close to.
	 * @param city: String of city name
	 * @param latitude: given latitude
	 * @param longitude: given longitude
	 * @return: sorted hotel array by proximity in the given city
	 */
	public Hotel[] getHotelsInCityByProximity(String city, double latitude, double longitude) {
		ArrayList<Hotel> hotelsInCity = new ArrayList<Hotel>();

		// city name is null or latitude/longitude are not valid
		if ((city == null) || (Math.abs(latitude) > MAX_LATITUDE_VALID) ||
			(Math.abs(longitude) > MAX_LONGITUDE_VALID)) {
			return hotelsInCity.toArray(new Hotel[0]);
		}

		hotelsInCity = allHotelsInCity(city);

		ProximityCompare proximityCompare = new ProximityCompare(latitude, longitude);
		Collections.sort(hotelsInCity, proximityCompare);

		return hotelsInCity.toArray(new Hotel[0]);
	}
}
<file_sep>/Ex2/src/SpaceShip.java
import java.awt.Image;

import oop.ex2.*;

import javax.swing.*;

/**
 * The API spaceships need to implement for the SpaceWars game. It is your decision whether SpaceShip.java
 * will be an interface, an abstract class, a base class for the other spaceships or any other option you will
 * choose.
 * @author <NAME>
 */
public abstract class SpaceShip {
	private SpaceShipPhysics shipPhysics;
	protected int max_energy;
	protected int current_energy;
	protected int health;
	protected boolean shield_is_on;
	protected int rounds_left_after_fire;

	/** The start level of maximal energy */
	private static final int START_MAX_ENERGY = 210;

	/** The start level of current energy */
	private static final int START_CURRENT_ENERGY = 190;

	/** The start level of health */
	private static final int START_HEALTH = 22;

	/** when there is no health */
	private static final int NO_HEALTH = 0;

	/** The reduce from the maximal energy level when shot without shield */
	private static final int REDUCE_MAX_ENERGY_WITHOUT_SHIELD = 10;

	/** Teleport energy cost */
	private static final int TELEPORT_ENERGY_COST = 140;

	/** Shield energy cost */
	private static final int SHIELD_ENERGY_COST = 3;

	/** Fire energy cost */
	private static final int FIRE_ENERGY_COST = 19;

	/** Rounds left after fire at the beginning */
	protected static final int NO_ROUNDS_LEFT_AFTER_FIRE = 0;

	/** Rounds left after fire */
	private static final int ROUNDS_LEFT_AFTER_FIRE = 7;

	/** No energy */
	private static final int NO_ENERGY = 0;

	/** Energy added because of bashing */
	private static final int BASH_ENERGY_ADD = 18;

	/** Symbols the ship turns left */
	protected static final int TURN_LEFT = 1;

	/** Symbols the ship turns right */
	protected static final int TURN_RIGHT = (-1);

	/** Symbols the ship doesnt turn */
	protected static final int NO_TURN = 0;

	/** Zero angle degree */
	protected static final double ZERO_ANGLE = 0;

	/** used to symbol accelerate as argument to the move method */
	protected static final boolean ACCELERATE = true;


	/**
	 * SpaceShip constructor sets all the data members to the default and create a new SpaceShipPhysics
	 */
	public SpaceShip() {
		shipPhysics = new SpaceShipPhysics();
		max_energy = START_MAX_ENERGY;
		current_energy = START_CURRENT_ENERGY;
		health = START_HEALTH;
		shield_is_on = false;
		rounds_left_after_fire = NO_ROUNDS_LEFT_AFTER_FIRE;
	}


	/**
	 * Does the actions of this ship for this round. This is called once per round by the SpaceWars game
	 * driver.
	 * @param game the game object to which this ship belongs.
	 */
	abstract void doAction(SpaceWars game);


	/**
	 * This method is called every time a collision with this ship occurs
	 */
	public void collidedWithAnotherShip() {
		if (shield_is_on) {
			max_energy += BASH_ENERGY_ADD;
			current_energy += BASH_ENERGY_ADD;
		} else {
			health--;
			max_energy -= REDUCE_MAX_ENERGY_WITHOUT_SHIELD;
			if (max_energy < NO_ENERGY) {
				max_energy = NO_ENERGY;
			}
			if (current_energy > max_energy) {
				current_energy = max_energy;
			}
		}
	}


	/**
	 * This method is called whenever a ship has died. It resets the ship's attributes, and starts it at a
	 * new
	 * random position.
	 */
	public void reset() {
		shipPhysics = new SpaceShipPhysics();
		max_energy = START_MAX_ENERGY;
		current_energy = START_CURRENT_ENERGY;
		health = START_HEALTH;
		shield_is_on = false;
		rounds_left_after_fire = NO_ROUNDS_LEFT_AFTER_FIRE;
	}


	/**
	 * Checks if this ship is dead.
	 * @return true if the ship is dead. false otherwise.
	 */
	public boolean isDead() {
		return health <= NO_HEALTH;
	}


	/**
	 * Gets the physics object that controls this ship.
	 * @return the physics object that controls the ship.
	 */
	public SpaceShipPhysics getPhysics() {
		return shipPhysics;
	}


	/**
	 * This method is called by the SpaceWars game object when ever this ship gets hit by a shot.
	 */
	public void gotHit() {
		if (!shield_is_on) {
			health--;
			max_energy -= REDUCE_MAX_ENERGY_WITHOUT_SHIELD;
			if (max_energy < NO_ENERGY) {
				max_energy = NO_ENERGY;
			}
			if (current_energy > max_energy) {
				current_energy = max_energy;
			}
		}
	}


	/**
	 * Gets the image of this ship. This method should return the image of the ship with or without the
	 * shield. This will be displayed on the GUI at the end of the round.
	 * @return the image of this ship.
	 */
	abstract Image getImage();


	/**
	 * Attempts to fire a shot.
	 * @param game the game object.
	 */
	public void fire(SpaceWars game) {
		if (current_energy < FIRE_ENERGY_COST) { // has enough energy
			return;
		}
		if (rounds_left_after_fire == NO_ROUNDS_LEFT_AFTER_FIRE) {    // possible to fire
			game.addShot(getPhysics());
			current_energy -= FIRE_ENERGY_COST;
			rounds_left_after_fire = ROUNDS_LEFT_AFTER_FIRE;
		}
	}


	/**
	 * Attempts to turn on the shield.
	 */
	public void shieldOn() {
		if (current_energy < SHIELD_ENERGY_COST) {   // has enough energy
			return;
		}
		current_energy -= SHIELD_ENERGY_COST;
		shield_is_on = true;
	}


	/**
	 * Attempts to teleport.
	 */
	public void teleport() {
		if (current_energy < TELEPORT_ENERGY_COST) { // has enough energy
			return;
		}
		current_energy -= TELEPORT_ENERGY_COST;
		shipPhysics = new SpaceShipPhysics();
	}

}
<file_sep>/Ex5/src/filesprocessing/Order.java
package filesprocessing;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;

import static filesprocessing.DirectoryProcessor.*;
import static filesprocessing.Errors.*;
import static filesprocessing.OrderFactory.*;

public class Order {

	/** abs order */
	protected static final String ABS = "abs";

	/** type order */
	protected static final String TYPE = "type";

	/** size order */
	protected static final String SIZE = "size";

	/** REVERSE suffix */
	protected static final String REVERSE = "REVERSE";

	/** start index of array */
	protected static final int START_OF_ARRAY = 0;


	/**
	 * check if the order line has a REVERSE suffix
	 * @param parsedLine: given parsed order line
	 * @return true if has and false if not
	 */
	private static boolean HasReverseSuffix(String[] parsedLine) {
		return parsedLine[parsedLine.length - 1].equals(REVERSE);
	}


	protected static void orderFiles(String orderLine, ArrayList<File> filteredFiles, int line_counter) {
		String[] parsedLine = orderLine.split(SEPARATOR_IN_LINE);
		boolean foundError = false;

		try {
			switch (parsedLine[0]) {

			case ABS:
				hasErrorInAbsOrder(parsedLine); // check for error
				Sort.sort(filteredFiles, START_OF_ARRAY, filteredFiles.size() - 1, absOrder());
				break;

			case TYPE:
				hasErrorInTypeOrder(parsedLine); // check for error
				Sort.sort(filteredFiles, START_OF_ARRAY, filteredFiles.size() - 1, typeOrder());
				break;

			case SIZE:
				hasErrorInSizeOrder(parsedLine); // check for error
				Sort.sort(filteredFiles, START_OF_ARRAY, filteredFiles.size() - 1, sizeOrder());
				break;

			default: // name is not valid
				foundError = true;
				break;

			}
		} catch (IllegalArgumentException exception) {
			foundError = true;
		}

		// found Type-1 error so order by abs
		if (foundError) {
			Sort.sort(filteredFiles, START_OF_ARRAY, filteredFiles.size() - 1, absOrder());
			System.err.println(WARNING_MESSAGE + line_counter);

		}

		if (!foundError && HasReverseSuffix(parsedLine)) {
			Collections.reverse(filteredFiles);
		}
	}

}
<file_sep>/Ex6/src/CheckIfWhile.java
import java.util.InvalidPropertiesFormatException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * class to check a line of if\while
 */
public class CheckIfWhile {

    private static final String EMPTY_STRING = "";
    private static final String TRUE = "true";
    private static final String FALSE = "false";
    private static final String BOOLEAN = "boolean";
    private static final String INT = "int";
    private static final String DOUBLE = "double";
    private static final String OPEN_ROUND_BRACKET = "(";

    private static final String ERROR_MESSAGE_CONDITION_INPUT_INVALID = "ERROR: condition input is invalid";
    private static final String ERROR_MESSAGE_INVALID_IF_WHILE_FORMAT
            = "ERROR: if\\while line format is invalid";


    /* regex of whitespace one or more times */
    private static final String REGEX_WHITESPACE = "\\s+";

    /* regex of || or && */
    private static final String REGEX_AND_OR_OR = "\\|\\||&&";

    /* regex of if\while format */
    private static final String REGEX_IF_WHILE_FORMAT =
            "\\s*(if|while)\\s*\\(\\s*([\\w.-]+)\\s*(\\s*(\\|\\||&&)" +
                    "\\s*[\\w.-]+\\s*)*\\s*\\)\\s*\\{\\s*";

    private static final Pattern patternIfWhile = Pattern.compile(REGEX_IF_WHILE_FORMAT);


    /**
     * check a single part of the condition is valid
     * @param input: a single part of the condition
     * @param thisScope: the current scope of the if\while
     * @throws InvalidPropertiesFormatException: throws if the pars is invalid
     */
    private static void checkConditionInput(String input, Scope thisScope)
            throws InvalidPropertiesFormatException {
        if ((input.equals(TRUE)) || (input.equals(FALSE))) {
            return;
        }
        try {
            Double.parseDouble(input);
        } catch (NumberFormatException e) {
            // if it isn't a number - maybe it is a variable name
            Variable variable = thisScope.findVariableInScopes(input);
            // if variable doesnt exist OR not initialized OR not in the correct Type (boolean\double\int)
            if ((variable == null) || (!variable.isInitialized()) || ((!variable.getType().equals(BOOLEAN)) &&
                    (!variable.getType().equals(INT)) &&
                    (!variable.getType().equals(DOUBLE)))) {
                throw new InvalidPropertiesFormatException(ERROR_MESSAGE_CONDITION_INPUT_INVALID);
            }
        }
    }


    /**
     * check just if the format of the line is a match to a valid if\while line
     * @param line: given string of a line
     * @return: true if the line match the format and false otherwise
     */
    public static boolean checkJustFormat(String line) {
        Matcher matcher = patternIfWhile.matcher(line);
        return matcher.matches();
    }


    /**
     * check a line of if\while - format and logic
     * @param line: string of a possible if\while line
     * @param thisScope: the current scope the if\while is in
     * @throws InvalidPropertiesFormatException: throws if the logic or the format is wrong
     */
    public static void checkIfWhileLine(String line, Scope thisScope)
            throws InvalidPropertiesFormatException {
        Matcher matcher = patternIfWhile.matcher(line);

        if (matcher.matches()) {
            int indexOfOpenBracket = line.indexOf(OPEN_ROUND_BRACKET);
            // take only the part after "("
            String subLine = line.substring(indexOfOpenBracket + 1);
            // remove all whitespaces
            subLine = subLine.replaceAll(REGEX_WHITESPACE, EMPTY_STRING);
            // take only the part before ")"
            subLine = subLine.substring(0, subLine.length() - 2);
            // split by || or &&
            String[] splitInputs = subLine.split(REGEX_AND_OR_OR);

            for (String input : splitInputs) {
                checkConditionInput(input, thisScope);
            }
        } else {
            throw new InvalidPropertiesFormatException(ERROR_MESSAGE_INVALID_IF_WHILE_FORMAT);
        }
    }
}<file_sep>/Ex1/src/TestOrel.java

/**
 * Created by: Evyatar
 * version 5.0
 * Changes history:
 * 23:07 ‎08/‎08/‎2020 - Orel -    willEnjoyBook can be >= and not >.
 * Test flow was adjusted accordingly in "test Library methods".
 * <p>
 * 01:37 ‎24/‎03/‎2018 - Kali -    When adding a patron that was already registered to the library, the
 * return value should by a !negative number! (as far as I understand the API),
 * unlike a book that was added twice - in that case should return existing book
 * id. Changed tests: 8.1, 14, 28.
 * 01:47 24/‎03/‎2018 - Kali -    Reverted changes (8.1, 14) due to forum answer.
 * <p>
 * 21:49 25/‎03/‎2018 - Evyatar - Now support any non-negative int's as ID's for books and patrons. Added two
 * libraries tests. willEnjoyBook has to be > and not >=.
 */
class TestOrel {
    TestOrel() {
    }

    public static void main(String[] args){

        // set up
        Book book1 = new Book("book1", "author1", 2001,
                2, 3, 1);
        Book book2 = new Book("book2", "author2", 2002,
                8, 3, 6);
        Book book3 = new Book("book2", "author2", 2002,
                8, 3, 6);
        Book book4 = new Book("book4", "author4", 2004,
                10, 10, 10);

        int book1ID, book2ID, book3ID, book4ID;

        Patron patron1 = new Patron("patron1", "last1", 3,
                5, 1, 21);
        Patron patron2 = new Patron("patron1", "last1", 2,
                1, 1, 0);
        Patron patron3 = new Patron("patron3", "last3", 2,
                1, 1, 0);

        int patron1ID1, patron2ID1, patron1ID2, patron2ID2;

        Library lib = new Library(3, 2, 2);


        // test book
        System.out.println("test Book methods");
        System.out.println();

        System.out.println(book1.stringRepresentation().equals("[book1,author1,2001,6]"));

        System.out.println(book1.getLiteraryValue() == 2 + 3 + 1);

        System.out.println(book1.getCurrentBorrowerId() < 0);

        book1.setBorrowerId(5);
        System.out.println(book1.getCurrentBorrowerId() == 5);
        book1.returnBook();


        // test patron
        System.out.println();

        System.out.println("test Patron methods");
        System.out.println();

        System.out.println("0.1:" + patron1.stringRepresentation().equals("patron1 last1"));

        System.out.println("0.2:" + (patron1.getBookScore(book1) == 3 * 2 + 5 * 3 + 1 * 1));

        System.out.println("0.3:" + patron1.willEnjoyBook(book1)); // 22>=22 [Summer 2020]
        System.out.println("0.4:" + patron1.willEnjoyBook(book2));


        // test library
        System.out.println();

        System.out.println("test Library methods");
        System.out.println();

        System.out.println("1: " + (!lib.isBookIdValid(1)));
        System.out.println("1.1: " + (!lib.isBookIdValid(88)));
        System.out.println("1.2: " + (!lib.isBookAvailable(1)));

        book1ID = lib.addBookToLibrary(book1);
        System.out.println("2: " + (book1ID >= 0));
        System.out.println("3: " + lib.isBookIdValid(book1ID));

        book2ID = lib.addBookToLibrary(book2);
        System.out.println("4: " + (book2ID >= 0));
        System.out.println("4.1: " + (book2ID != book1ID));
        System.out.println("4.2: " + (lib.isBookIdValid(book2ID)));
        System.out.println("4.3: " + (lib.addBookToLibrary(book2) == book2ID)); // add the same book, should
        // return the index of original and shouldn't save another copy.

        book3ID = lib.addBookToLibrary(book3); // book with same  arguments
        System.out.println("5: " + (book3ID >= 0 && book3ID != book1ID && book3ID != book2ID));

        System.out.println("6: " + (lib.addBookToLibrary(book4) < 0)); // no room
        System.out.println("6.1: " + (lib.addBookToLibrary(book2) == book2ID)); // add the same book when
        // there is no room.

        System.out.println("7: " + (!lib.isPatronIdValid(1)));
        System.out.println("7.1: " + (!lib.isPatronIdValid(8)));

        patron1ID1 = lib.registerPatronToLibrary(patron1);
        System.out.println("8:" + (patron1ID1 >= 0));
        System.out.println("9:" + (lib.registerPatronToLibrary(patron1) == patron1ID1));
        System.out.println("10: " + (lib.isPatronIdValid(patron1ID1)));

        patron2ID1 = lib.registerPatronToLibrary(patron2);
        System.out.println("11: " + (lib.registerPatronToLibrary(patron2) == patron2ID1));
        System.out.println("12: " + (lib.isPatronIdValid(patron2ID1)));

        System.out.println("13: " + (lib.registerPatronToLibrary(patron3) < 0));
        System.out.println("14: " + (lib.registerPatronToLibrary(patron1) == patron1ID1));

        System.out.println("15: " + (lib.getPatronId(patron2) == patron2ID1));

        // tests for 'borrowBook'
        System.out.println("16: " + (lib.isBookAvailable(book1ID)));

        // actually will enjoy (22>=22)
        System.out.println("17: " + (lib.borrowBook(book1ID, patron1ID1)));

        System.out.println("18: " + (!lib.borrowBook(book1ID, patron2ID1)));   // the book is taken
        System.out.println("19: " + (!lib.isBookAvailable(book1ID)));
        System.out.println("20: " + (lib.borrowBook(book2ID, patron1ID1)));
        System.out.println("21: " + (!lib.borrowBook(80, patron2ID1))); // book id is not valid
        System.out.println("22: " + (!lib.borrowBook(book3ID, 80))); // patron id is not
        // valid
        System.out.println("23: " + (!lib.borrowBook(book2ID, patron1ID1)));
        System.out.println("24: " + (!lib.borrowBook(book3ID, patron1ID1))); // too many books for one patron
        lib.returnBook(book1ID);
        System.out.println("25: " + (lib.borrowBook(book3ID, patron2ID1)));
        System.out.println("26: " + (book1.getCurrentBorrowerId() < 0));


        System.out.println("27: " + (lib.getBookId(lib.suggestBookToPatron(patron2ID1)) == book1ID));
        System.out.println("28: " + (lib.suggestBookToPatron(patron1ID1) == book1));

        book1.comicValue -= 1;

        // null because book2 and book3 are taken and he will not enjoy book1
        System.out.println("29: " + (lib.suggestBookToPatron(patron1ID1) == null));

        // two libraries tests
        Library lib2 = new Library(1, 1, 2);
        System.out.println();
        System.out.println("two libraries tests");
        System.out.println();

        System.out.println("30: " + (!lib2.isBookIdValid(0)));

        book4ID = lib2.addBookToLibrary(book4);
        System.out.println("31: " + (book4ID >= 0));


        patron1ID2 = lib2.registerPatronToLibrary(patron1);
        patron2ID2 = lib2.registerPatronToLibrary(patron2);

        System.out.println("32: " + (patron1ID2 >= 0));
        System.out.println("33: " + (patron2ID2 >= 0));
        System.out.println("34: " + (patron1ID2 != patron2ID2));

        System.out.println("35: " + (lib2.borrowBook(book4ID, patron1ID2))); // patron1 has the max number
        // of books in library1, should be able to borrow in another library.

    }
}
<file_sep>/Ex6/src/Test.java
/**
 * הוראות שימוש (בעברית, כי נמאס כבר מתיעודים באנגלית)
 * שימו את הקובץ הנוכחי בתיקיית
 * src
 * שלכם בסמוך לחבילה
 * oop.ex6
 * כדי שיהיה אפשר להריץ ושהוא יכיר את התכנית שלכם
 *
 * יש שני שדות סטטים, אחד צריך להכיל את הנתיב לתיקייה עם כל הטסטים שהם נתנו (הקבצי
 * javac)
 * השדה נקרא
 * testDirPath
 * השדה השני צריך להכיל את הנתיב לקובץ סיכום שהם נתנו
 * sjavac_tests.txt
 * זהו השדה
 * exceptedFilePath
 *
 * מה שהטסט עושה זה מריץ את התכנית שלכם על כל הקבצים (היא אמורה להדפיס 0 או 1 בכל פעם)
 * ובסמוך לכל טסט להדפיס את השורה הרלוונטית בקובץ שלהם, כך תוכלו להשוות את הערך שמתקבל
 * ולבדוק שהתכנית שלכם נופלת באמת בגלל הסיבה הזאת
 *
 * שימו לב שיש קבצים שאין להם שורה מתאימה בקובץ ולידם לא יודפס כלום.
 *
 * המלצה שלי- בכל פעם שהתכנית מדפיסה 1 תדפיסו את הסיבה לכך אצלכם וכך יהיה נוח להשוות
 *
 */
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.HashMap;
import java.util.Objects;

public class Test {
    // enter here the path to tests directory
    public static final String testDirPath = "G:\\My Drive\\year2-semesterA\\OOP\\Exercises\\Ex6\\tests";
    // enter here the path to sjavac_tests.txt
    public static final String exceptedFilePath = "G:\\My Drive\\year2-semesterA\\OOP\\Exercises\\Ex6\\sjavac_tests.txt";

    public static void main(String[] args) {


        File tesDir = new File(testDirPath);
        try {
            FileReader reader = new FileReader(exceptedFilePath);
            BufferedReader bReader = new BufferedReader(reader);
            HashMap<String, String> filesLines = new HashMap<>();
            String line = "";
            while (line != null) {
                line = bReader.readLine();
                while (line.equals("")) {
                    line = bReader.readLine();
                    if(line == null) {
                        break;
                    }
                }
                if(line == null) {
                    break;
                }
                String fileName = line.substring(0, 13);
                filesLines.put(fileName, line);
            }
            for (File file : Objects.requireNonNull(tesDir.listFiles())) {
                String[] arguments = {file.getAbsolutePath()};
                System.out.println("_________\n" + file.getName());
                Sjavac.main(arguments);
                if (filesLines.containsKey(file.getName())) {
                    System.out.println(filesLines.get(file.getName()));
                }
                System.out.println("_________");
            }
        } catch (Exception ignored) {
        }
    }
}
<file_sep>/Ex2/src/Aggressive.java
import oop.ex2.GameGUI;

import java.awt.*;

/**
 * A class that represents an Aggressive SpaceShip
 */
public class Aggressive extends SpaceShip {

	/** The angle the aggressive need to be from another spaceship to try firing */
	private static final double MAX_ANGLE_TO_FIRE = 0.21;

	/**
	 * Does the actions of this ship for this round. This is called once per round by the SpaceWars game
	 * driver. This ship pursues other ships and tries to fire at them. It will always accelerate, and turn
	 * towards the nearest ship. When its angle to the nearest ship is less than 0.21 radians, it will try to
	 * fire.
	 * @param game the game object to which this ship belongs.
	 */
	public void doAction(SpaceWars game) {
		//------------- Accelerate and Turn -------------
		SpaceShip closest = game.getClosestShipTo(this);
		double angle_to_closest = this.getPhysics().angleTo(closest.getPhysics());
		double distance_from_closest = this.getPhysics().distanceFrom(closest.getPhysics());
		int turn;
		if (angle_to_closest < ZERO_ANGLE) {
			turn = TURN_RIGHT;
		} else if (angle_to_closest > ZERO_ANGLE) {
			turn = TURN_LEFT;
		} else {
			turn = NO_TURN;
		}
		getPhysics().move(ACCELERATE, turn);

		//------------- Firing a shot -------------
		if (rounds_left_after_fire != NO_ROUNDS_LEFT_AFTER_FIRE) {
			rounds_left_after_fire--;
		} else if (Math.abs(angle_to_closest) < MAX_ANGLE_TO_FIRE) {
			fire(game);
		}

		//------------- Add 1 Energy unit -------------
		if (current_energy < max_energy) {
			current_energy++;
		}
	}


	/**
	 * Gets the image of this ship. This method should return the image of the ship with or without the
	 * shield. This will be displayed on the GUI at the end of the round.
	 * @return the image of this ship.
	 */
	public Image getImage() {
		if (shield_is_on) {
			return GameGUI.ENEMY_SPACESHIP_IMAGE_SHIELD;
		}
		return GameGUI.ENEMY_SPACESHIP_IMAGE;
	}

}

<file_sep>/Ex5/src/filesprocessing/OrderFactory.java
package filesprocessing;

import java.io.File;
import java.util.Comparator;


public class OrderFactory {

	/** equal in comparator */
	protected static final int EQUAL = 0;

	/** period doesnt exist in the file name */
	protected static final int PERIOD_DOES_NOT_EXIST = (-1);

	/** the index at the beginning of a string */
	protected static final int FIRST_STRING_INDEX = 0;


	/**
	 * compare between files name (in lexicographically order)
	 * @return 0 iff their size is equal, number bigger than 0 if file1 > file2 and number smaller than 0 if
	 * 		file1 < file2
	 */
	protected static Comparator<File> absOrder() {
		return (file1, file2) -> (file1.getAbsolutePath().compareTo(file2.getAbsolutePath()));
	}


	/**
	 * find the file's type
	 * @param file: file to find the type of
	 * @return the extension after the last point in the name string
	 */
	private static String findFileType(File file) {
		String fileName = file.getName();
		String fileType;
		int fileLastPointIndex = fileName.lastIndexOf(".");

		if (file.isHidden()) { // if hidden
			if ((fileLastPointIndex == FIRST_STRING_INDEX) || (fileLastPointIndex == fileName.length() - 1)) {
				fileType = "";
			} else {
				fileType = fileName.substring(fileLastPointIndex + 1);
			}

		} else { // not hidden
			if ((fileLastPointIndex == PERIOD_DOES_NOT_EXIST) ||
				(fileLastPointIndex == fileName.length() - 1)) {
				fileType = "";
			} else {
				fileType = fileName.substring(fileLastPointIndex + 1);
			}
		}
		return fileType;
	}


	/**
	 * compare between files type (in lexicographically order)
	 * @return 0 iff their size is equal, number bigger than 0 if file1 > file2 and number smaller than 0 if
	 * 		file1 < file2
	 */
	protected static Comparator<File> typeOrder() {
		return (file1, file2) -> {
			int compare_value = findFileType(file1).compareTo(findFileType(file2));
			return (compare_value == EQUAL) ? file1.getAbsolutePath().compareTo(file2.getAbsolutePath()) :
				   compare_value;
		};
	}


	/**
	 * compare between files size
	 * @return 0 iff their size is equal, number bigger than 0 if file1 > file2 and number smaller than 0 if
	 * 		file1 < file2
	 */
	protected static Comparator<File> sizeOrder() {
		return (file1, file2) -> {
			int compare_value = Long.compare(file1.length(), file2.length());
			return (compare_value == EQUAL) ? file1.getAbsolutePath().compareTo(file2.getAbsolutePath()) :
				   compare_value;
		};
	}


}
<file_sep>/Ex1/src/TesterAdir.java
//written by Adir
import java.lang.reflect.Method;

public class TesterAdir {
    public static final String ANSI_RED = "\u001B[31m";
    public static final String ANSI_RESET = "\u001B[0m";
    public static final String ANSI_CYAN = "\u001B[36m";
    public static final String ANSI_BG = "\u001B[46m";

    public static void main(String[] args) {
        //general API structure check
        System.out.println("Checking if API methods exists in Book class...");
        checkingMethodExistsBook();
        System.out.println("Checking if API methods exists in Patron class...");
        checkingMethodExistsPatron();
        System.out.println("Checking if API methods exists in Library class...");
        checkingMethodExistsLibrary();

        System.out.println("Running Book basic tests...");
        BookSanityTests();
        System.out.println("Running Patron basic tests...");
        PatronBasicTests();
        System.out.println("Running Library basic tests...");
        LibraryBasicTests();
        LibraryBasicTests2();
        semiMsg("ALL TESTS PASSED!");
    }

    public static void LibraryBasicTests2() {
        int n = 5;
        Patron[] patrons = new Patron[n];
        Book[] books = new Book[n];
        int[] patronsID = new int[n];
        int[] booksID = new int[n];
        Library lib = new Library(n,n,n);
        for (int i = 0; i < n; i++) {
            patrons[i] = new Patron("a", "b", 1, 1, 1, 1);
            books[i] = new Book("a","b",2001,1,1,1);
            patronsID[i] = lib.registerPatronToLibrary(patrons[i]);
            booksID[i] = lib.addBookToLibrary(books[i]);
        }
        for(int i = 0; i < n; i++){
            if(patronsID[i] != lib.getPatronId(patrons[i])){
                writeError("ERROR: getPatronID: Incorrect patron's ID.");
            }
            if(booksID[i] != lib.getBookId(books[i])){
                writeError("ERROR: getPatronID: Incorrect patron's ID.");
            }
            if(!lib.isBookIdValid(booksID[i])){
                writeError("ERROR: isBookIdValid returned false, but ID is valid.");
            }
            if(!lib.isPatronIdValid(patronsID[i])){
                writeError("ERROR: isPatronIdValid returned false, but ID is valid.");
            }
        }
        if(lib.isBookIdValid(23123)) { //random id
            writeError("ERROR: isBookIdValid returned true for random id.");
        }
        if(lib.isPatronIdValid(23123)) { //random id
            writeError("ERROR: isPatronIdValid returned true for random id.");
        }
        writeSuccess("getBookId and getPatronId - VALID");
        writeSuccess("isBookIdValid and isPatronIdValid - VALID");
        for(int i = 0; i < n;i++){
            if(!lib.isBookAvailable(booksID[i])){
                writeError("ERROR: Available book labeled as borrowed.");
            }
            lib.borrowBook(booksID[i],patronsID[i]);
            if(lib.isBookAvailable(booksID[i])){
                writeError("ERROR: Borrowed book labeled as available.");
            }
        }
        boolean c = lib.isBookAvailable(-1);
        if(c){
            writeError("ERROR: isBookAvailable returned True for boolId=-1.");
        }
        //c = false
        c = true;
        c = lib.isBookAvailable(23123);//random id
        if(c){
            writeError("ERROR: isBookAvailable return True for random id.");
        }
        lib.returnBook(booksID[0]);
        lib.returnBook(booksID[1]);
        if(!lib.borrowBook(booksID[0],patronsID[1]) || !lib.borrowBook(booksID[1],patronsID[0])) {
            writeError("ERROR: Trying to borrow returned book failed.");
        }
        lib.returnBook(booksID[0]);
        lib.returnBook(booksID[0]); //double return, check if program collapse.
        lib.returnBook(-1); //check invalid id
        lib.returnBook(202020); //check valid id but not in the library.
        writeSuccess("returnBook - VALID");
        Library lib2 = new Library(4,2,2);
        Patron patron1 = new Patron("a","b",2,2,2,6);
        Patron patron2 = new Patron("a","b",3,4,3,1);
        Book b1 = new Book("t","a",2001,1,1,1);
        Book b2 = new Book("t","a",2003,1,2,1);
        Book b3 = new Book("t","a",2004,2,2,2);
        Book b4 = new Book("t","a",2004,2,2,2);
        lib2.addBookToLibrary(b1);
        lib2.addBookToLibrary(b2);
        lib2.addBookToLibrary(b3);
        lib2.addBookToLibrary(b4);
        lib2.registerPatronToLibrary(patron1);
        lib2.registerPatronToLibrary(patron2);
        lib2.borrowBook(lib2.getBookId(b2),lib2.getPatronId(patron1));
        if(lib2.suggestBookToPatron(lib2.getPatronId(patron1)) != b3){
            writeError("ERROR: Incorrect book returned from suggestBookToPatron.(1)");
        }
        lib2.borrowBook(lib2.getBookId(b3), lib2.getPatronId(patron2));
        if(lib2.suggestBookToPatron(lib2.getPatronId(patron1)) != b4){
            writeError("ERROR: Incorrect book returned from suggestBookToPatron.(2)");
        }
        lib2.borrowBook(lib2.getBookId(b4), lib2.getPatronId(patron1));
        //patron 1 with 2 books (b2,b4)
        //patron 2 with 1 book b3
        //patron 1 won't enjoy any other book, so should get null
        if(lib2.suggestBookToPatron(lib2.getPatronId(patron1)) != null){
            writeError("ERROR: Incorrect book returned from suggestBookToPatron.(3)");
        }
        //patron 2 will enjoy b1.
        if(lib2.suggestBookToPatron(lib2.getPatronId(patron2)) != b1){
            writeError("ERROR: Incorrect book returned from suggestBookToPatron.(4)");
        }
        writeSuccess("suggestBookToPatron - VALID");

    }

    public static void LibraryBasicTests() {
        Library lib = new Library(1, 1, 1);
        Patron p = new Patron("d", "d", 1, 1, 1, 20);
        Patron p2 = new Patron("dd", "dd", 2, 2, 2, 20);
        Book b = new Book("A", "A", 2000, 1, 1, 1);
        Book b2 = new Book("B", "B", 2000, 2, 2, 2);
        int bookId = lib.addBookToLibrary(b);
        if (bookId < 0) {
            writeError("ERROR: Adding a book to the library returned negative id.");
        }
        int bookId2 = lib.addBookToLibrary(b);
        if (bookId != bookId2) {
            writeError("ERROR: Adding the same book object succeeded.");
        }
        int shouldNotBeIn = lib.addBookToLibrary(b2);
        if (shouldNotBeIn >= 0) {
            writeError("ERROR: Capacity is full, but adding book succeeded.");
        }
        writeSuccess("Book addition, copies handling, capacity - VALID");
        int patronId = lib.registerPatronToLibrary(p);
        if (patronId < 0) {
            writeError("ERROR: Registering patron to the library returned negative id.");
        }
        int patronId2 = lib.registerPatronToLibrary(p);
        if (patronId != patronId2) {
            writeError("ERROR: Adding the same patron object succeeded.");
        }
        int shouldNotBeIn2 = lib.registerPatronToLibrary(p2);
        if (shouldNotBeIn2 >= 0) {
            writeError("ERROR: Capacity is full, but adding patron succeeded.");
        }
        writeSuccess("Patron registration, double registration handling, capacity - VALID");
        Library lib2 = new Library(3, 1, 1);
        Patron patron1 = new Patron("patron1", "patron1", 2, 2, 2, 10);
        Book book11 = new Book("book1", "a1", 2001, 4, 4, 4);
        Book book12 = new Book("book2", "a1", 2001, 3, 1, 1);
        Book book13 = new Book("book2", "a1", 2001, 5, 5, 5);
        int patron1ID = lib2.registerPatronToLibrary(patron1);
        int book11ID = lib2.addBookToLibrary(book11);
        int book12ID = lib2.addBookToLibrary(book12);
        //פטרון משאיל ספר שהוא לא יהנה ממנו
        boolean x = lib2.borrowBook(book12ID, patron1ID);
        if (x) {
            writeError("ERROR: Patron succeeded to borrow he won't enjoy.");
        }
        //פטרון מנסה להשאיל ספר שלא קיים
        boolean xx = lib2.borrowBook(book12ID + 20, patron1ID);
        //פטרון מנסה להשאיל ספר שכבר מושאל
        if (xx) {
            writeError("ERROR: Patron succeeded to borrow that doesn't exist.");
        }
        boolean xxx = lib2.borrowBook(book12ID, patron1ID + 20);
        if (xxx) {
            writeError("ERROR: Incorrect patron's ID succeeded to borrow.");
        }
        boolean xxxx = lib2.borrowBook(book11ID, patron1ID);
        if (!xxxx) {
            writeError("ERROR: Patron failed to borrow valid book.");
        }
        //פטרון מנסה להשאיל ספר למרות שהוא כבר משאיל הכל
        boolean y = lib2.borrowBook(book11ID, patron1ID);
        if (y) {
            writeError("ERROR: Patron succeeded to borrow unavailable book.");
        }
        int book3ID = lib2.addBookToLibrary(book13);
        boolean z = lib2.borrowBook(book3ID, patron1ID);
        if (z) {
            writeError("ERROR: Patron succeeded to borrow 2 books, but max borrow is 1.");
        }
        writeSuccess("Borrowing tests - VALID");

    }

    public static void PatronBasicTests() {
        Patron p = new Patron("Some", "Name", 4, 3, 11, 33);
        Book b1 = new Book("A", "B", 2001, 1, 1, 1);
        Book b2 = new Book("A", "B", 2001, 2, 1, 2);
        Book b3 = new Book("A", "B", 2001, 3, 1, 2);
        if (p.getBookScore(b1) != (4 + 3 + 11)) {
            writeError("Patron's getBookScore FAILED, should be " + (4 + 3 + 11) + ".");
        }
        if (p.getBookScore(b2) != (4 * 2 + 3 + 11 * 2)) {
            writeError("Patron's getBookScore FAILED, should be " + (4 * 2 + 3 + 11 * 2) + ".");
        }
        writeSuccess("Patron's getBookScore PASSED");
        if (!p.stringRepresentation().equals("Some Name")) {
            writeError("Patron's stringRepresentation FAILED, expected:Some Name got: " + p.stringRepresentation());
        }
        writeSuccess("Patron's stringRepresentation PASSED");
        if (p.willEnjoyBook(b1)) {
            //enjoyment of b1 is 18 < 33 - should be false.
            writeError("Patron's willEnjoyBook FAILED, should be false.");
        }
        if (p.willEnjoyBook(b2)) {
            //enjoyment of b2 is 33 - should be false.
            writeError("Patron's willEnjoyBook FAILED, should be false.");
        }
        if (!p.willEnjoyBook(b3)) {
            //enjoyment of b3 is 37 > 33 - should be true.
            writeError("Patron's willEnjoyBook FAILED, should be true.");
        }
        writeSuccess("Patron's willEnjoyBook PASSED");
        semiMsg("Basic tests of Patron PASSED");

    }

    public static void BookSanityTests() {
        Book test = new Book("A", "B", 2009, 4, 12, 5);
        if (test.getLiteraryValue() != (4 + 12 + 5)) {
            writeError("Book's getLiteraryValue FAILED");
        }
        writeSuccess("Book's getLiteraryValue PASSED");
        if (!test.stringRepresentation().equals("[A,B,2009," + (4 + 12 + 5) + "]")) {
            writeError("Book's stringRepresentation FAILED");
        }
        writeSuccess("Book's stringRepresentation PASSED");
        if (test.getCurrentBorrowerId() != -1) {
            writeError("Book's getCurrentBorrowerId FAILED, should be -1.");
        }
        int borrowerID = 15;
        test.setBorrowerId(borrowerID);
        if (test.getCurrentBorrowerId() != borrowerID) {
            writeError("Book's getCurrentBorrowerId FAILED, should be " + borrowerID + ".");
        }
        writeSuccess("Book's getCurrentBorrowerId and setBorrowerId PASSED");
        test.returnBook();
        test.returnBook();
        if (test.getCurrentBorrowerId() != -1) {
            writeError("Book's returnBook FAILED, getCurrentBorrowerId() should return -1.");
        }
        writeSuccess("Book's returnBook PASSED");
        semiMsg("Basic tests of Book PASSED");
    }

    public static void checkingMethodExistsBook() {
        //checking Constructor
        Book b = new Book("Title", "Author", 2000, 1, 1, 1);
        writeSuccess("Book Constructor EXISTS");
        int checkIntReturn = b.getCurrentBorrowerId(); //won't compile unless getCurrentBorrowerId exists and returns int.
        writeSuccess("Book getCurrentBorrowerId EXISTS and return type's VALID");
        checkIntReturn = b.getLiteraryValue();  //won't compile unless getCurrentBorrowerId exists and returns int.
        writeSuccess("Book getLiteraryValue EXISTS and return type's VALID");
        b.returnBook();
        try {
            Method m = Book.class.getDeclaredMethod("returnBook");
            if (m.getReturnType().equals(Void.TYPE)) {
                writeSuccess("Book returnBook EXISTS and return type's VALID");
            } else {
                writeError("ERROR: Book returnBook's return type is not void.");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        b.setBorrowerId(10);
        try {
            Method m = Book.class.getDeclaredMethod("setBorrowerId", int.class);
            if (m.getReturnType().equals(Void.TYPE)) {
                writeSuccess("Book setBorrowerId EXISTS and return type's VALID");
            } else {
                writeError("ERROR: Book setBorrowerId's return type is not void.");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        String t = b.stringRepresentation();
        writeSuccess("Book stringRepresentation EXISTS and return type's VALID");
        semiMsg("Book class includes all API methods - VALID");
    }

    public static void checkingMethodExistsPatron() {
        Patron p = new Patron("First", "Name", 1, 1, 1, 10);
        writeSuccess("Patron Constructor EXISTS");
        Book b = new Book("Title", "Author", 2001, 1, 1, 1);
        int d = p.getBookScore(b);
        writeSuccess("Patron getBookScore EXISTS and return type's VALID");
        boolean s = p.willEnjoyBook(b);
        writeSuccess("Patron willEnjoyBook EXISTS and return type's VALID");
        String s1 = p.stringRepresentation();
        writeSuccess("Patron stringRepresentation EXISTS and return type's VALID");
        semiMsg("Patron class includes all API methods - VALID");
    }

    public static void checkingMethodExistsLibrary() {
        Library lib = new Library(1, 1, 1);
        Patron p = new Patron("A", "B", 1, 1, 1, 1);
        Book b = new Book("a", "b", 2009, 1, 1, 2);
        writeSuccess("Library Constructor EXISTS");
        int d = lib.addBookToLibrary(b);
        boolean s = lib.borrowBook(0, 2); //invalid id's!!
        writeSuccess("Library addBookToLibrary EXISTS and return type's VALID");
        d = lib.getBookId(b);
        writeSuccess("Library getBookId EXISTS and return type's VALID");
        d = lib.getPatronId(p);
        writeSuccess("Library getPatronId EXISTS and return type's VALID");
        s = lib.isBookAvailable(0);
        writeSuccess("Library isBookAvailable EXISTS and return type's VALID");
        s = lib.isBookIdValid(0);
        writeSuccess("Library isBookIdValid EXISTS and return type's VALID");
        s = lib.isPatronIdValid(0);
        writeSuccess("Library isPatronIdValid EXISTS and return type's VALID");
        d = lib.registerPatronToLibrary(p);
        writeSuccess("Library registerPatronToLibrary EXISTS and return type's VALID");
        try {
            Method m = Library.class.getDeclaredMethod("returnBook", int.class);
            if (m.getReturnType().equals(Void.TYPE)) {
                writeSuccess("Library returnBook EXISTS and return type's VALID");
            } else {
                writeError("ERROR: Library returnBook's return type is not void.");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        Book t = lib.suggestBookToPatron(0);
        writeSuccess("Library suggestBookToPatron EXISTS and return type's VALID");
        semiMsg("Library class includes all API methods - VALID");

    }

    public static void writeError(String msg) {
        System.out.println(ANSI_RED + msg + ANSI_RESET);
        System.exit(0);
    }

    public static void writeSuccess(String msg) {
        System.out.println(ANSI_CYAN + msg + ANSI_RESET);
    }

    public static void semiMsg(String msg) {
        System.out.println("=========================================");
        System.out.println(ANSI_BG + msg + ANSI_RESET);
        System.out.println("=========================================");
    }
}

<file_sep>/Ex6/src/MethodCall.java
/**
 * MethodCall class saving the name and values given as parameters
 */
public class MethodCall {
    private String name;
    private String[] values;

    /**
     * Basic constructor
     * @param name
     * @param values
     */
    public MethodCall(String name, String[] values){
        this.name = name;
        this.values = values;
    }

    /**
     * Getting the name of the method we are calling to
     * @return
     */
    public String getName(){
        return name;
    }

    /**
     * Getting the values to send as parameters
     * @return
     */
    public String[] getValues(){
        return values;
    }
}
<file_sep>/Ex1/src/TestAdi.java
import org.junit.Assert;

public class TestAdi {
    TestAdi() {
        test3();
    }

    public void test3() {
        // make libraries and patrons:
        Library library1 = new Library(3, 2, 3);
        Library library2 = new Library(1, 1, 1);
        Book book1 = new Book("<NAME> 1", "<NAME>", 1996,
                              3, 1, 3);
        Book book2 = new Book("<NAME>", "<NAME>.", 1996,
                              3, 2, 1);
        Book book3 = new Book("Hello", "<NAME>", 1996,
                              2, 3, 1);
        Book book4 = new Book("Hello 2", "<NAME>", 1996,
                              1, 1, 1);
        Patron patron1 = new Patron("Adi", "Shimoni",
                                    3, 1, 1, 7);
        Patron patron2 = new Patron("Adi2", "Shimoni",
                                    1313, 5, 2, 7);
        Patron patron3 = new Patron("Adi3", "Shimoni",
                                    2, 100, 1, 2);
        Patron patron4 = new Patron("Adi4", "Shimoni",
                                    0, 0, 0, 0);

        // register patrons:
        int b = library1.registerPatronToLibrary(patron1);
        boolean s = library1.isPatronIdValid(1);
        Assert.assertFalse(s);
        int k = library1.registerPatronToLibrary(patron2);
        int l = library1.registerPatronToLibrary(patron3);
        int ll = library1.registerPatronToLibrary(patron3);
        Assert.assertEquals(2, ll);
        boolean m = library1.isPatronIdValid(0);
        Assert.assertTrue(m);
        library1.getPatronId(patron1);

        int jjj = library1.registerPatronToLibrary(patron3);
        int kkk = library1.registerPatronToLibrary(patron2);
        int mmm = library1.registerPatronToLibrary(patron1);
        Assert.assertEquals(3, jjj + kkk + mmm);

        // add books library 1:
        int a = library1.addBookToLibrary(book1);
        Assert.assertEquals(0, a);
        library1.addBookToLibrary(book2);
        library1.addBookToLibrary(book3);
        int mm = library1.addBookToLibrary(book3);
        Assert.assertEquals(2, mm);
        boolean c = library1.borrowBook(2, 0);
        Assert.assertTrue(c);
        library1.returnBook(2);
        boolean d = library1.borrowBook(2, 0);
        Assert.assertTrue(d);
        library1.returnBook(2);
        boolean r = library1.borrowBook(2, 0);
        Assert.assertTrue(r);
        Book whichBook = library1.suggestBookToPatron(0);
        Book whichBook2 = library1.suggestBookToPatron(1);
        Book whichBook3 = library1.suggestBookToPatron(2);
        Assert.assertEquals("[<NAME> 1,<NAME>,1996,7]", whichBook.stringRepresentation());
        Assert.assertEquals("[<NAME>,<NAME>.,1996,6]", whichBook2.stringRepresentation());
        Assert.assertEquals("[<NAME>,<NAME>.,1996,6]", whichBook3.stringRepresentation());


        int aaaa = library2.addBookToLibrary(book1);
        Assert.assertEquals(0, aaaa);
        library2.addBookToLibrary(book2);
        library2.addBookToLibrary(book3);
        int mmmm = library2.addBookToLibrary(book3);
        Assert.assertEquals(-1, mmmm);
        boolean cc = library2.borrowBook(2, 0);
        Assert.assertFalse(cc);
        library2.returnBook(2);
        boolean dd = library2.borrowBook(2, 0);
        Assert.assertFalse(dd);
        library2.returnBook(2);
        boolean rr = library2.borrowBook(2, 0);
        Assert.assertFalse(rr);
        Book whichBook111 = library2.suggestBookToPatron(0);
        Book whichBook222 = library2.suggestBookToPatron(1);
        Book whichBook333 = library2.suggestBookToPatron(2);
        Assert.assertNull(whichBook111);
        Assert.assertNull(whichBook222);
        Assert.assertNull(whichBook333);
    }
}
<file_sep>/Ex5/src/filesprocessing/Filter.java
package filesprocessing;


import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.Arrays;


import static filesprocessing.DirectoryProcessor.*;
import static filesprocessing.Errors.*;
import static filesprocessing.FilterFactory.*;


public class Filter {

	/** greater_than filter */
	protected static final String GREATER_THAN = "greater_than";

	/** between filter */
	protected static final String BETWEEN = "between";

	/** smaller_than filter */
	protected static final String SMALLER_THAN = "smaller_than";

	/** file filter */
	protected static final String FILE = "file";

	/** contains filter */
	protected static final String CONTAINS = "contains";

	/** prefix filter */
	protected static final String PREFIX = "prefix";

	/** suffix filter */
	protected static final String SUFFIX = "suffix";

	/** writable filter */
	protected static final String WRITABLE = "writable";

	/** executable filter */
	protected static final String EXECUTABLE = "executable";

	/** hidden filter */
	protected static final String HIDDEN = "hidden";

	/** all filter */
	protected static final String ALL = "all";

	/** NOT suffix */
	protected static final String NOT = "NOT";

	/** empty string */
	protected static final String EMPTY_STRING = "";

	/** length of array of size 1 */
	protected static final int LENGTH_OF_ONE = 1;


	static boolean foundError = false;


	/**
	 * check if the filter line has a NOT suffix
	 * @param parsedLine: given parsed filter line
	 * @return true if has and false if not
	 */
	private static boolean HasNotSuffix(String[] parsedLine) {
		return parsedLine[parsedLine.length - 1].equals(NOT);
	}


	/**
	 * returns a filter by greater_than
	 * @param parsedLine: given parsed filter line
	 * @return FileFilter filtering files by greater_than
	 */
	private static FileFilter filterGreaterThan(String[] parsedLine) {
		try {
			hasErrorInGreaterThanFilter(parsedLine); // check for errors

			if (HasNotSuffix(parsedLine)) {
				return greaterThanCheck(Double.parseDouble(parsedLine[1]), true);
			}
			return greaterThanCheck(Double.parseDouble(parsedLine[1]), false);
		} catch (IllegalArgumentException e) {
			foundError = true;
			return null;
		}
	}


	/**
	 * returns a filter by between
	 * @param parsedLine: given parsed filter line
	 * @return FileFilter filtering files by between
	 */
	private static FileFilter filterBetween(String[] parsedLine) {
		try {
			hasErrorInBetweenFilter(parsedLine);// check for errors

			if (HasNotSuffix(parsedLine)) {
				return betweenCheck(Double.parseDouble(parsedLine[1]), Double.parseDouble(parsedLine[2]),
									true);
			}
			return betweenCheck(Double.parseDouble(parsedLine[1]), Double.parseDouble(parsedLine[2]),
								false);
		} catch (IllegalArgumentException | ArithmeticException exception) {
			foundError = true;
			return null;
		}
	}


	/**
	 * returns a filter by smaller_than
	 * @param parsedLine: given parsed filter line
	 * @return FileFilter filtering files by smaller_than
	 */
	private static FileFilter filterSmallerThan(String[] parsedLine) {
		try {
			hasErrorInSmallerThanFilter(parsedLine); // check for errors
			if (HasNotSuffix(parsedLine)) {
				return smallerThanCheck(Double.parseDouble(parsedLine[1]), true);
			}
			return smallerThanCheck(Double.parseDouble(parsedLine[1]), false);
		} catch (IllegalArgumentException exception) {
			foundError = true;
			return null;
		}
	}


	/**
	 * returns a filter by file
	 * @param parsedLine: given parsed filter line
	 * @return FileFilter filtering files by file
	 */
	private static FileFilter filterFile(String[] parsedLine) {
		try {
			hasErrorInFileFilter(parsedLine); // check for errors

			if (HasNotSuffix(parsedLine)) {
				return fileCheck(parsedLine[1], true);
			}
			return fileCheck(parsedLine[1], false);
		} catch (IllegalArgumentException exception) {
			foundError = true;
			return null;
		}
	}


	/**
	 * returns a filter by contains
	 * @param parsedLine: given parsed filter line
	 * @return FileFilter filtering files by contains
	 */
	private static FileFilter filterContains(String[] parsedLine) {
		try {
			hasErrorInContainsFilter(parsedLine); // check for errors

			if (HasNotSuffix(parsedLine)) {
				return containsCheck(parsedLine[1], true);
			}
			if (parsedLine.length == LENGTH_OF_ONE) { // in case for "contains#" (empty string after #)
				return containsCheck(EMPTY_STRING, false);
			}
			return containsCheck(parsedLine[1], false);
		} catch (IllegalArgumentException exception) {
			foundError = true;
			return null;
		}
	}


	/**
	 * returns a filter by prefix
	 * @param parsedLine: given parsed filter line
	 * @return FileFilter filtering files by prefix
	 */
	private static FileFilter filterPrefix(String[] parsedLine) {
		try {
			hasErrorInPrefixFilter(parsedLine); // check for errors

			if (HasNotSuffix(parsedLine)) {
				return prefixCheck(parsedLine[1], true);
			}
			if (parsedLine.length == LENGTH_OF_ONE) { // in case for "prefix#" (empty string after #)
				return prefixCheck(EMPTY_STRING, false);
			}
			return prefixCheck(parsedLine[1], false);
		} catch (IllegalArgumentException exception) {
			foundError = true;
			return null;
		}
	}


	/**
	 * returns a filter by suffix
	 * @param parsedLine: given parsed filter line
	 * @return FileFilter filtering files by suffix
	 */
	private static FileFilter filterSuffix(String[] parsedLine) {
		try {
			hasErrorInSuffixFilter(parsedLine); // check for errors

			if (HasNotSuffix(parsedLine)) {
				return suffixCheck(parsedLine[1], true);
			}
			if (parsedLine.length == LENGTH_OF_ONE) { // in case for "suffix#" (empty string after #)
				return suffixCheck(EMPTY_STRING, false);
			}
			return suffixCheck(parsedLine[1], false);
		} catch (IllegalArgumentException exception) {
			foundError = true;
			return null;
		}
	}


	/**
	 * returns a filter by writable
	 * @param parsedLine: given parsed filter line
	 * @return FileFilter filtering files by writable
	 */
	private static FileFilter filterWritable(String[] parsedLine) {
		try {
			hasErrorInWritableFilter(parsedLine); // check for errors

			if (HasNotSuffix(parsedLine)) {
				return writableCheck(parsedLine[1], true);
			}
			return writableCheck(parsedLine[1], false);
		} catch (IllegalArgumentException exception) {
			foundError = true;
			return null;
		}
	}


	/**
	 * returns a filter by executable
	 * @param parsedLine: given parsed filter line
	 * @return FileFilter filtering files by executable
	 */
	private static FileFilter filterExecutable(String[] parsedLine) {
		try {
			hasErrorInExecutableFilter(parsedLine); // check for errors
			if (HasNotSuffix(parsedLine)) {
				return executableCheck(parsedLine[1], true);
			}
			return executableCheck(parsedLine[1], false);
		} catch (IllegalArgumentException exception) {
			foundError = true;
			return null;
		}
	}


	/**
	 * returns a filter by hidden
	 * @param parsedLine: given parsed filter line
	 * @return FileFilter filtering files by hidden
	 */
	private static FileFilter filterHidden(String[] parsedLine) {
		try {
			hasErrorInHiddenFilter(parsedLine); // check for errors

			if (HasNotSuffix(parsedLine)) {
				return hiddenCheck(parsedLine[1], true);
			}
			return hiddenCheck(parsedLine[1], false);
		} catch (IllegalArgumentException exception) {
			foundError = true;
			return null;
		}
	}


	/**
	 * returns a filter by all
	 * @param parsedLine: given parsed filter line
	 * @return FileFilter filtering files by all
	 */
	private static FileFilter filterAll(String[] parsedLine) {
		try {
			hasErrorInAllFilter(parsedLine); // check for errors

			if (HasNotSuffix(parsedLine)) {
				return allCheck(true);
			}
			return allCheck(false);
		} catch (IllegalArgumentException exception) {
			foundError = true;
			return null;
		}
	}


	/**
	 * filter the files in the sourceDir directory according to the filter in the given filter line
	 * @param filterLine: String of the filter line
	 * @param sourceDir: Directory to filter files from
	 * @param line_counter: counter the current line in the Commands file
	 * @return ArrayList<File> of the filtered files in the sourceDir directory
	 */
	protected static ArrayList<File> filterFiles(String filterLine, File sourceDir, int line_counter) {
		String[] parsedLine = filterLine.split(SEPARATOR_IN_LINE);

		File[] files;
		FileFilter filter = null;

		switch (parsedLine[0]) {

		case GREATER_THAN:
			filter = filterGreaterThan(parsedLine);
			break;

		case BETWEEN:
			filter = filterBetween(parsedLine);
			break;

		case SMALLER_THAN:
			filter = filterSmallerThan(parsedLine);
			break;

		case FILE:
			filter = filterFile(parsedLine);
			break;

		case CONTAINS:
			filter = filterContains(parsedLine);
			break;

		case PREFIX:
			filter = filterPrefix(parsedLine);
			break;

		case SUFFIX:
			filter = filterSuffix(parsedLine);
			break;

		case WRITABLE:
			filter = filterWritable(parsedLine);
			break;

		case EXECUTABLE:
			filter = filterExecutable(parsedLine);
			break;

		case HIDDEN:
			filter = filterHidden(parsedLine);
			break;


		case ALL:
			filter = filterAll(parsedLine);
			break;

		default: // name is not valid
			foundError = true;
			break;
		}

		if (foundError) {
			filter = allCheck(false);
			System.err.println(WARNING_MESSAGE + line_counter);
			foundError = false;
		}

		// filter the files
		files = sourceDir.listFiles(filter);

		// move filtered files to ArrayList (easier to sort with)
		ArrayList<File> filesArrayList = null;
		if (files != null) {
			filesArrayList = new ArrayList<File>(Arrays.asList(files));
		}

		return filesArrayList;
	}
}
<file_sep>/Ex3/src/LongTermStorage.java
import oop.ex3.spaceship.Item;

import java.util.TreeMap;


/**
 * Implementation of a Long-Term storage class
 */
public class LongTermStorage extends Storage {

	/** total storage unit capacity of long-term storage */
	private static final int TOTAL_LTS_CAPACITY = 1000;


	/**
	 * constructor of LongTermStorage
	 */
	public LongTermStorage() {
		this.capacity = TOTAL_LTS_CAPACITY;
		this.available_capacity = TOTAL_LTS_CAPACITY;
	}


	/**
	 * try to add n items of the given item to the storage
	 * @param item: type of item to add
	 * @param n: number of items to add
	 * @return: 0 if addition was successful (-1) if there is not enough space in storage
	 */
	public int addItem(Item item, int n) {
		if ((n < 0) || (item == null)) { // invalid input
			System.out.println(MESSAGE_GENERAL_ERROR);
			return VALUE_MINUS_ONE;
		}
		if (available_capacity < (item.getVolume() * n)) {
			System.out.println(MESSAGE_NO_ROOM_BEGIN + n + MESSAGE_ITEMS_OF_TYPE + item.getType());
			return VALUE_MINUS_ONE;
		}
		if (n > 0) { // add just if amount is positive
			if (itemsCount.containsKey(item.getType())) { // item exist in itemsCount
				itemsCount.put(item.getType(), itemsCount.get(item.getType()) + n);
			} else {    // item does not exist in itemsCount
				itemsCount.put(item.getType(), n);
			}
			available_capacity -= (n * item.getVolume());
		}
		return VALUE_ZERO;
	}


	/**
	 * reset and delete all the items in the LTS
	 */
	public void resetInventory() {
		available_capacity = TOTAL_LTS_CAPACITY;
		itemsCount = new TreeMap<String, Integer>();
	}
}
<file_sep>/Ex5/src/test/python_tests/tester_python.py
"""
SecondaryTester for OOP, exercise 5.
"""
import textwrap
from os import listdir
# from os import startfile
from os.path import isfile, join, isdir, exists
from os import path
import subprocess

tester_ver = 1.3
ASCII_ERROR = """
______  _______  _______  _______  _______ 
(  ____ \(  ____ )(  ____ )(  ___  )(  ____ )
| (    \/| (    )|| (    )|| (   ) || (    )|
| (__    | (____)|| (____)|| |   | || (____)|
|  __)   |     __)|     __)| |   | ||     __)
| (      | (\ (   | (\ (   | |   | || (\ (   
| (____/\| ) \ \__| ) \ \__| (___) || ) \ \__
(_______/|/   \__/|/   \__/(_______)|/   \__/
"""
ASCII_PASSES = """
  , ; ,   .-'^^^'-.   , ; ,
  \\|/  .'         '.  \|//
   \-;-/   ()   ()   \-;-/
   // ;               ; \\
  //__; :.         .; ;__\\
 `-----\'.'-.....-'.'/-----'
        '.'.-.-,_.'.'
          '(  (..-'
            '-'
"""

# paths to files and folder
path_to_test_files = path.join("tester_files")
path_to_tests = path.join(path_to_test_files, "tests")
path_to_type_2_tests = path.join(path_to_test_files, "tests_error_type_2")
path_to_files_to_filter = path.join(path_to_test_files, "files_to_filter")

folders_of_files_to_filter = ['simple', 'complex']

path_to_java_files = path.join("src")
path_to_compiled_files = path.join(path_to_test_files, "compiled_files")
path_to_DirectoryProcessor_compiled = path.join("filesprocessing.DirectoryProcessor")
path_to_filesprocessing = path.join(path_to_java_files, "filesprocessing")
path_to_DirectoryProcessor_not_compiled = path.join(path_to_filesprocessing,
                                                    "DirectoryProcessor.java")

# name of files
name_of_user_output_file_no_folder = "_user" + "_output" + ".txt"
name_of_user_errors_file_no_folder = "_user" + "_errors" + ".txt"
name_of_commands_file = "commands.txt"
name_of_school_solution_output_no_folder = "_school_solution" + "_output" + ".txt"
name_of_school_solution_errors_no_folder = "_school_solution" + "_errors" + ".txt"
name_of_p_file = path.join(path_to_files_to_filter, folders_of_files_to_filter[1], "99..size-8780.NHDR.png")


def can_not_test(msg):
    print("Error:", msg)
    input("press Enter to exit")
    exit(1)


def run_with_cmd(command_list):
    """
    Execute the given command list with the command line
    Return a tuple containing the return code, output and errors.
    """

    process = subprocess.Popen(command_list, stdin=subprocess.PIPE,
                               stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)

    output, errors = process.communicate()
    return process.returncode, output, errors


def print_with_indentation(title, to_print):
    """print text in a nice way"""
    prefix = title + ": "
    wrapper = textwrap.TextWrapper(initial_indent=prefix, break_long_words=False,
                                   subsequent_indent=' ' * len(prefix))
    print(wrapper.fill(to_print))


def compile_file():
    """
    compile the java files. the compiled files are located in \test_files\compiled_files.
    terminate the tester if there was an error.
    :return: true if was successful.
    """
    if not exists(path_to_java_files) or not isdir(path_to_java_files):
        can_not_test("You don't have the folder: " + path_to_java_files)
    if not exists(path_to_DirectoryProcessor_not_compiled):
        can_not_test("You don't have the file: " + path_to_DirectoryProcessor_not_compiled)
    if not exists(path_to_filesprocessing) or not isdir(path_to_filesprocessing):
        can_not_test("You don't have the folder: " + path_to_filesprocessing)
    if not exists(path_to_DirectoryProcessor_not_compiled):
        can_not_test("You don't have the file: " + path_to_DirectoryProcessor_not_compiled)

    command_list = ['javac', '-d', path_to_compiled_files,
                    '-cp', path_to_java_files, path_to_DirectoryProcessor_not_compiled]

    code, output, errors = run_with_cmd(command_list)
    if code != 0:
        can_not_test("problem with compiling\n"+"error message\n"+errors)
    print("compile OK\n\n")


def run_one_test(test_folder_name, files_to_filter_folder):
    """
    run one test. run your code with command file given and with the data given. sva the rusolts in a txt file.
    then compare it to the school solution txt file.
    :param test_folder_name: the name of the folder of the test (tests/test#)
    :param files_to_filter_folder: the data folder  (simple of complex)
    :return: true if was successful.
    """
    path_to_test_folder = path.join(path_to_tests, test_folder_name)
    path_to_command_file = path.join(path_to_test_folder, name_of_commands_file)

    name_of_school_solution_output = files_to_filter_folder + name_of_school_solution_output_no_folder
    name_of_school_solution_errors = files_to_filter_folder + name_of_school_solution_errors_no_folder

    path_to_school_solution_output = path.join(path_to_test_folder, name_of_school_solution_output)
    path_to_school_solution_errors = path.join(path_to_test_folder, name_of_school_solution_errors)

    name_of_user_output = files_to_filter_folder + name_of_user_output_file_no_folder
    name_of_user_errors = files_to_filter_folder + name_of_user_errors_file_no_folder

    path_to_user_output = path.join(path_to_test_folder, name_of_user_output)
    path_to_user_errors = path.join(path_to_test_folder, name_of_user_errors)

    path_to_files_to_filter_folder = path.join(path_to_files_to_filter, files_to_filter_folder)

    print("starting", test_folder_name, "with data folder", files_to_filter_folder+"..")

    command_list = ["java", '-cp', path_to_compiled_files, path_to_DirectoryProcessor_compiled,
                    path_to_files_to_filter_folder,
                    path_to_command_file]

    code, user_output, user_errors = run_with_cmd(command_list)  # run your code

    # save the files output and errors
    with open(path_to_user_output, 'w') as output_file:
        output_file.write(user_output)

    with open(path_to_user_errors, 'w') as errors_file:
        errors_file.write(user_errors)

    # compare to school solution
    compare_outputs = compare_files(path_to_school_solution_output, path_to_user_output)
    compare_errors = compare_files(path_to_school_solution_errors, path_to_user_errors)

    # print helpful information if there was mistakes.
    if compare_outputs is not None or compare_errors is not None:
        # compare failed
        if compare_outputs is not None:
            print("Output file compare failed: here are the details:")
            print_with_indentation("output compare", compare_outputs)
        if compare_errors is not None:
            print("Errors file compare failed: here are the details:")
            print_with_indentation("errors compare", compare_errors)
        return False
    print("passed :)")
    return True


def compare_files(file1, file2):
    """
    compare to files with FC (windows file comparer)
    :param file1:
    :param file2:
    :return: the compaction text if there was errors
    """
    command_to_compare = ['fc', '/W', '/N', '/A', file1, file2]
    code, output, errors = run_with_cmd(command_to_compare)
    if code != 0:  # if code != 0
        return output
    return None


def run_tests():
    """
    run all the test in the folder test_files\tests with both data folders (simple, complex)
    :return: true iff all passed
    """
    all_passed = True
    tests_names = [t for t in listdir(path_to_tests) if isdir(join(path_to_tests, t))]  # list of test names
    number_of_tests = len(tests_names) * len(folders_of_files_to_filter)
    passed_tests = 0
    for folder_to_filter in folders_of_files_to_filter:  # the two data folders
        print("##########  testing with data -", folder_to_filter, "  ##########\n")
        for test_name in tests_names:  # each test
            if run_one_test(test_name, folder_to_filter):
                passed_tests += 1
            else:
                all_passed = False
            print()
        print()
    if all_passed:
        print("All tests passed!!")
        return True
    else:
        print("passes", passed_tests, "out of", number_of_tests, "tests")
        return False


def run_type_2_tests():
    """
    run all type-2 tests
    :return: true iff all passed
    """
    print("\n##########   type-2 error tests:  ##########\n")
    folder_to_filter = path.join(path_to_files_to_filter, folders_of_files_to_filter[0])
    path_to_test = path.join(path_to_type_2_tests, "no_file_with_that_name.txt")
    passed1 = run_one_type_2_test(folder_to_filter, path_to_test, "no_command_file")

    folder_to_filter = path.join(path_to_files_to_filter, folders_of_files_to_filter[0])
    path_to_test = path.join(path_to_type_2_tests, "no_file_with_that _name.txt")
    passed2 = run_one_type_2_test(folder_to_filter, path_to_test, "too many parameters")

    folder_to_filter = path.join(path_to_files_to_filter, folders_of_files_to_filter[0])
    path_to_test = ""
    passed3 = run_one_type_2_test(folder_to_filter, path_to_test, "only 1 parameter")

    return type_2_tests() and passed1 and passed2 and passed3


def type_2_tests():
    """
    run all the test in the folder test_files\tests_error_type_2
    :return: true iff all passed
    """
    all_passed = True
    tests_names = [f for f in listdir(path_to_type_2_tests) if isfile(join(path_to_type_2_tests, f))]
    number_of_tests = len(tests_names)
    passed_tests = 0
    for test in tests_names:
        folder_to_filter = path.join(path_to_files_to_filter, folders_of_files_to_filter[0])
        path_to_test = path.join(path_to_type_2_tests, test)
        passed = run_one_type_2_test(folder_to_filter, path_to_test, test)
        if passed:
            passed_tests += 1
        else:
            all_passed = False
    if all_passed:
        print("All type-2 error tests passed!!")
        return True
    else:
        print("passes", passed_tests, "out of", number_of_tests, "type-2 error tests")
        return False


def passed_all():
    print(ASCII_PASSES)
    print("you passed everything!!! \ngo get some sleep")
    # startfile(name_of_p_file)


def run_one_type_2_test(folder_to_filter, path_to_test, test):
    """run one type-2 test"""
    command = ["java", '-cp', path_to_compiled_files, path_to_DirectoryProcessor_compiled,
               folder_to_filter,
               path_to_test]
    code, output, errors = run_with_cmd(command)
    if output or not errors:
        print("test-type-2", test, "failed. nothing should be printed as filtered. and an error should "
                                   "be printed. the print was:\n")
        print_with_indentation("output", output)

        print_with_indentation("errors", errors)
        print("\ncontinue...\n")
        passed = False
    else:
        print("test-type-2", test, "passed")
        passed = True
    return passed


if __name__ == "__main__":
    while True:
        print("starting tester for ex5 version", tester_ver, '\n')
        compile_file()
        tests_passed = run_tests()
        type_2_passed = run_type_2_tests()

        if tests_passed and type_2_passed:
            passed_all()
        else:
            print(ASCII_ERROR)

        input("press enter to restart the tester")
        print('\n\n\nRestarting...')
<file_sep>/Ex3/src/Locker.java
import oop.ex3.spaceship.Item;


/**
 * Locker implementation class
 */
public class Locker extends Storage {

	/** items moved to LTS message */
	private static final String MESSAGE_ITEMS_MOVED_TO_LTS = "Warning: Action successful, but has caused " +
															 "items to be moved to storage";

	/** tried to remove a negative number of items message */
	private static final String MESSAGE_REMOVE_NEGATIVE_NUMBER = "Error: Your request cannot be completed " +
																 "at this time. Problem: cannot remove a " +
																 "negative number of items of type ";

	/** error message of not containing enough items to remove - beginning */
	private static final String MESSAGE_REMOVE_LESS_THAN_CONTAIN_BEGIN = "Error: Your request cannot be " +
																		 "completed at this time. Problem:" +
																		 " the locker does not contain ";

	/** error message of found constraint - begin */
	private static final String MESSAGE_FOUND_CONSTRAINT_BEGIN = "Error: Your request cannot be completed " +
																 "at this time. Problem: the locker cannot" +
																 " contain items of type ";

	/** error message of found constraint - end */
	private static final String MESSAGE_FOUND_CONSTRAINT_END = ", as it contains a contradiction item";

	/** symbols a return function value of minus two */
	private static final int VALUE_MINUS_TWO = (-2);

	/** symbols a no amount of item in locker */
	private static final int ZERO_AMOUNT = 0;


	private LongTermStorage lts = null;
	private Item[][] constraints = null;


	/**
	 * constructor of Locker
	 * @param lts: LongTermStorage of the spaceship
	 * @param capacity: total capacity of this locker
	 * @param constraints: array of size-2 arrays of all the constraints between the items
	 */
	public Locker(LongTermStorage lts, int capacity, Item[][] constraints) {
		this.lts = lts;
		this.constraints = constraints;
		this.capacity = capacity;
		this.available_capacity = capacity;
	}


	/**
	 * trying to remove items from the locker.
	 * @param item: type of item to remove
	 * @param n: number of the given item to remove
	 * @return: (- 1) if n is negative or n is bigger the actual amount 0 if remove succeeded
	 */
	public int removeItem(Item item, int n) {
		if (item == null){
			System.out.println(MESSAGE_GENERAL_ERROR);
			return VALUE_MINUS_ONE;
		}
		// n is negative
		else if (n < 0) {
			System.out.println(MESSAGE_REMOVE_NEGATIVE_NUMBER + item.getType());
			return VALUE_MINUS_ONE;
		}
		// n is bigger the amount of item in the locker
		else if (getItemCount(item.getType()) < n) {
			System.out.println(
					MESSAGE_REMOVE_LESS_THAN_CONTAIN_BEGIN + n + MESSAGE_ITEMS_OF_TYPE + item.getType());
			return VALUE_MINUS_ONE;
		}
		// locker doesnt contain the item
		if (!itemsCount.containsKey(item.getType())){
			return VALUE_ZERO;
		}
		// n is equal to amount of item in the locker
		if (n == itemsCount.get(item.getType())) {
			itemsCount.remove(item.getType());
		} else {    // n is less than the amount of item in the locker
			itemsCount.put(item.getType(), itemsCount.get(item.getType()) - n);
		}
		available_capacity += (n * item.getVolume());
		return VALUE_ZERO;
	}


	/**
	 * check if the given item take more the 50% of locker's space
	 * @param item: given item
	 * @param amountToAdd: number of items trying to add
	 * @return true if more the 50% and false otherwise
	 */
	private boolean moreThan50(Item item, int amountToAdd) {
		int total_volume_of_type;
		total_volume_of_type = (getItemCount(item.getType()) + amountToAdd) * item.getVolume();
		return total_volume_of_type > (FIFTY_PERCENT * capacity);
	}


	/**
	 * check if locker can keep all 20% of the item or not. if the locker can the method calls the
	 * addItemsToLockerAndLTS to check if there is enough space in LTS. If the LTS does have, the method
	 * will add the correct amount to the locker and the LTS.
	 * @param item: given item
	 * @param amountToAdd: given amount to move to add to locker
	 * @return true if there is enough space: and do the addition false if there isn't enough space
	 */
	private boolean tryToAddToLTS(Item item, int amountToAdd) {
		// current amount + amount to add
		int total_item_amount = amountToAdd + getItemCount(item.getType());
		// (20% of total locker capacity) / (item's volume)
		int max_items_number_can_keep_in_locker = (int) (TWENTY_PERCENT * capacity) / item.getVolume();
		int min_number_of_items_to_move_to_LTS = total_item_amount - max_items_number_can_keep_in_locker;

		return addItemsToLockerAndLTS(item, max_items_number_can_keep_in_locker,
									  min_number_of_items_to_move_to_LTS);
	}


	/**
	 * check if there is enough space in LTS. If the LTS does have, the method will add the correct amount
	 * to the locker and the LTS.
	 * @param item: item to add
	 * @param number_of_items_can_keep_in_locker: number of items to add to locker
	 * @param number_of_items_must_move_to_LTS: number of items to add to LTS
	 * @return true is enough room in LTS and false otherwise.
	 */
	private boolean addItemsToLockerAndLTS(Item item, int number_of_items_can_keep_in_locker,
										   int number_of_items_must_move_to_LTS) {

		if (lts.addItem(item, number_of_items_must_move_to_LTS) == VALUE_ZERO) {
			if (itemsCount.containsKey(item.getType())) { // item exist in itemsCount
				// remove old item amount in locker
				available_capacity += item.getVolume() * itemsCount.get(item.getType());
			}
			// update to the new amount in locker
			itemsCount.put(item.getType(), number_of_items_can_keep_in_locker);
			// update the available capacity
			available_capacity -= item.getVolume() * number_of_items_can_keep_in_locker;
			return true;
		}
		return false;
	}


	/**
	 * trying to add the given amount of the given item to the locker's space
	 * @param item: given item
	 * @param n: amount of items to add
	 * @return -1 	if there is not enough room in the locker or LTS, or n is a negative number 1 	if some
	 * 		items have to move to LTS and there is place for them 0	if succeeded to add and no items have
	 * 		been
	 * 		moved to LTS
	 */
	public int addItem(Item item, int n) {
		if ((item == null) || (item.getType() == null)) {
			System.out.println(MESSAGE_GENERAL_ERROR);
			return VALUE_MINUS_ONE;
		}

		boolean foundConstraint = false;

		for (String storedItem : itemsCount.keySet()) {
			for (Item[] constraint : constraints) {
				if ((constraint[0].getType().equals(storedItem) &&
					 constraint[1].getType().equals(item.getType()))
					||
					(constraint[0].getType().equals(item.getType()) &&
					 constraint[1].getType().equals(storedItem))) {
						foundConstraint = true;
				}
			}
		}
		if (foundConstraint) {
			System.out
					.println(MESSAGE_FOUND_CONSTRAINT_BEGIN + item.getType() + MESSAGE_FOUND_CONSTRAINT_END);
			return VALUE_MINUS_TWO;
		}

		if (n < 0) { // n is negative
			System.out.println(MESSAGE_GENERAL_ERROR);
			return VALUE_MINUS_ONE;

		}
		//not enough space in locker for all n items
		else if (available_capacity < (item.getVolume() * n)) {
			System.out.println(MESSAGE_NO_ROOM_BEGIN + n + MESSAGE_ITEMS_OF_TYPE + item.getType());
			return VALUE_MINUS_ONE;
		}

		if (moreThan50(item, n)) { // space of item will be more than 50%
			if (tryToAddToLTS(item, n)) {    // there is enough space in LTS
				System.out.println(MESSAGE_ITEMS_MOVED_TO_LTS);
				return VALUE_ONE;
			}
			// not enough space in LTS
			// (The printout is already printed in the addItem of LTS)
			return VALUE_MINUS_ONE;
		}

		if (n > 0) {    // add items just if n positive
			if (itemsCount.containsKey(item.getType())) { // item exist in itemsCount
				itemsCount.put(item.getType(), itemsCount.get(item.getType()) + n);
			} else {    // item does not exist in itemsCount
				itemsCount.put(item.getType(), n);
			}
			available_capacity -= (n * item.getVolume());
		}
		return VALUE_ZERO;
	}


}
<file_sep>/Ex3/src/BoopingSiteTest.java
import oop.ex3.searchengine.Hotel;
import org.junit.*;

import static org.junit.Assert.*;


public class BoopingSiteTest {


	/** name file of hotels_tst1 which has only one city */
	private static final String DATASET_ONE_CITY = "hotels_tst1.txt";

	/** name file of hotels_tst2 which is empty */
	private static final String DATASET_EMPTY = "hotels_tst2.txt";

	/** name file of hotels_dataset which is the full dataset */
	private static final String DATASET_FULL = "hotels_dataset.txt";

	/** city name not in database */
	private static final String CITY_NOT_IN_DATABASE = "makore";

	/** city name in database */
	private static final String CITY_IN_DATABASE = "manali";

	/** representing the maximum star rating possible */
	private static final int MAXIMUM_STAR_RATING = 5;

	/** representing a valid double latitude degree [-90,90] */
	private static final double VALID_LATITUDE = 85.2;

	/** representing double value over 90 degree */
	private static final double OVER_90_LATITUDE = 91.1;

	/** representing double value below (-90) degree */
	private static final double BELOW_MINUS_90_LATITUDE = (-91.3);

	/** representing a valid double longitude degree [-180,180] */
	private static final double VALID_LONGITUDE = 150.4;

	/** representing double value over 180 degree */
	private static final double OVER_180_LONGITUDE = 180.8;

	/** representing double value below (-180) degree */
	private static final double BELOW_MINUS_180_LONGITUDE = (-183.6);

	/** representing the numbers of hotels in DATASET_ONE_CITY (all of them) */
	private static final int NUMBER_OF_HOTELS_IN_DATASET_ONE_CITY = 70;

	/** representing the numbers of hotels in DATASET_EMPTY (no hotels because it's empty) */
	private static final int NUMBER_OF_HOTELS_IN_DATASET_EMPTY = 0;

	/** representing the smallest string possible according to the alphabet order */
	private static final String SMALLEST_STRING_POSSIBLE = "a";

	/** representing the equal value is returned from comparator method */
	private static final int COMPARE_EQUAL = 0;


	BoopingSite boopingSite_empty = new BoopingSite(DATASET_EMPTY);
	BoopingSite boopingSite_one_city = new BoopingSite(DATASET_ONE_CITY);
	BoopingSite boopingSite_full = new BoopingSite(DATASET_FULL);


	/**
	 * reset the boopingSite after each test
	 */
	@Before
	public void reset() {
		boopingSite_empty = new BoopingSite(DATASET_EMPTY);
		boopingSite_one_city = new BoopingSite(DATASET_ONE_CITY);
		boopingSite_full = new BoopingSite(DATASET_FULL);
	}


	/**
	 * test constructor function
	 */
	@Test
	public void constructorTest() {
		assertNotNull(boopingSite_empty);
		assertNotNull(boopingSite_one_city);
		assertNotNull(boopingSite_full);
	}


	/**
	 * test getHotelsInCityByRating function
	 */
	@Test
	public void getHotelsInCityByRatingTest() {
		hotelsInCityByRatingTest(boopingSite_empty);
		hotelsInCityByRatingTest(boopingSite_one_city);
		hotelsInCityByRatingTest(boopingSite_full);
	}


	/**
	 * test getHotelsInCityByRating function with given BoopingSite object
	 */
	private void hotelsInCityByRatingTest(BoopingSite boopingSite) {

		// --------------------- invalid inputs ---------------------
		Hotel[] empty_hotel_array = new Hotel[0];
		// no hotels in the given city (==city not in database)
		assertArrayEquals(empty_hotel_array, boopingSite.getHotelsInCityByRating(CITY_NOT_IN_DATABASE));

		// given city name is null
		assertArrayEquals(empty_hotel_array, boopingSite.getHotelsInCityByRating(null));


		// --------------------- valid inputs ---------------------
		Hotel[] sorted_rating_hotels = boopingSite.getHotelsInCityByRating(CITY_IN_DATABASE);
		int last_star_rating = MAXIMUM_STAR_RATING;
		String last_hotel_name = SMALLEST_STRING_POSSIBLE;

		// moving across all returned hotels and check if their rating and name is in descending order
		for (Hotel hotel : sorted_rating_hotels) {
			// current rate is bigger than last
			assertFalse(hotel.getStarRating() > last_star_rating);
			// if they have the same rating => check current name is before the last name in alphabet order
			if (hotel.getStarRating() == last_star_rating) {
				assertFalse(last_hotel_name.compareTo(hotel.getPropertyName()) < COMPARE_EQUAL);
			}
			last_star_rating = hotel.getStarRating();
			last_hotel_name = hotel.getPropertyName();
		}
	}


	/**
	 * calculating the distance from (x1,y1) to (x2,y2) according to the Euclidean distance
	 * @param x1 : double of latitude
	 * @param y1 : double of longitude
	 * @return double of the distance
	 */
	private double calculateDistance(double x1, double y1) {
		return Math.sqrt(((BoopingSiteTest.VALID_LONGITUDE - y1) * (BoopingSiteTest.VALID_LONGITUDE - y1)) +
						 ((BoopingSiteTest.VALID_LATITUDE - x1) * (BoopingSiteTest.VALID_LATITUDE - x1)));
	}


	/**
	 * test getHotelsByProximity function
	 */
	@Test
	public void getHotelsByProximityTest() {
		hotelsByProximityTest(boopingSite_empty);
		hotelsByProximityTest(boopingSite_one_city);
		hotelsByProximityTest(boopingSite_full);
	}


	/**
	 * test getHotelsByProximity function with given BoopingSite object
	 */
	private void hotelsByProximityTest(BoopingSite boopingSite) {
		// --------------------- invalid inputs ---------------------
		Hotel[] empty_hotel_array = new Hotel[0];
		// invalid: latitude > 90
		assertArrayEquals(empty_hotel_array,
						  boopingSite.getHotelsByProximity(OVER_90_LATITUDE, VALID_LONGITUDE));

		// invalid: latitude < (-90)
		assertArrayEquals(empty_hotel_array,
						  boopingSite.getHotelsByProximity(BELOW_MINUS_90_LATITUDE, VALID_LONGITUDE));

		// invalid: longitude > 180
		assertArrayEquals(empty_hotel_array,
						  boopingSite.getHotelsByProximity(VALID_LATITUDE, OVER_180_LONGITUDE));

		// invalid: longitude < (-180)
		assertArrayEquals(empty_hotel_array,
						  boopingSite.getHotelsByProximity(VALID_LATITUDE, BELOW_MINUS_180_LONGITUDE));

		// --------------------- valid inputs ---------------------
		Hotel[] sorted_proximity_hotels = boopingSite.getHotelsByProximity(VALID_LATITUDE, VALID_LONGITUDE);

		// checking the number of hotels in sorted_proximity_hotels
		if (boopingSite == boopingSite_empty) {
			assertEquals(NUMBER_OF_HOTELS_IN_DATASET_EMPTY, sorted_proximity_hotels.length);

		} else if (boopingSite == boopingSite_one_city) {
			assertEquals(NUMBER_OF_HOTELS_IN_DATASET_ONE_CITY, sorted_proximity_hotels.length);
		}

		double last_distance = 0.0; // initialize to not important value
		int last_POIs_number = 0;
		boolean first_hotel = true;

		// moving across all hotels and check if their proximity and POIs are in the right order
		for (Hotel hotel : sorted_proximity_hotels) {
			if (first_hotel) {
				last_distance = calculateDistance(hotel.getLatitude(), hotel.getLongitude());
				last_POIs_number = hotel.getNumPOI();
				first_hotel = false;
				continue;
			}

			double curr_distance = calculateDistance(hotel.getLatitude(), hotel.getLongitude());
			// current distance is smaller than lat distance
			assertFalse(curr_distance < last_distance);
			// if they have the same distance => check if curr number of POI is bigger than last POI number
			if (curr_distance == last_distance) {
				assertFalse(last_POIs_number < hotel.getNumPOI());
			}

			last_distance = curr_distance;
			last_POIs_number = hotel.getNumPOI();
		}
	}


	/**
	 * test getHotelsByProximity function
	 */
	@Test
	public void getHotelsInCityByProximityTest() {
		hotelsInCityByProximityTest(boopingSite_empty);
		hotelsInCityByProximityTest(boopingSite_one_city);
		hotelsInCityByProximityTest(boopingSite_full);
	}


	/**
	 * test getHotelsInCityByProximity function with given BoopingSite object
	 */
	private void hotelsInCityByProximityTest(BoopingSite boopingSite) {
		// --------------------- invalid inputs ---------------------
		Hotel[] empty_hotel_array = new Hotel[0];
		// invalid: city not in database
		assertArrayEquals(empty_hotel_array, boopingSite
				.getHotelsInCityByProximity(CITY_NOT_IN_DATABASE, VALID_LATITUDE, VALID_LONGITUDE));

		// invalid: city's name is null
		assertArrayEquals(empty_hotel_array, boopingSite
				.getHotelsInCityByProximity(null, VALID_LATITUDE, VALID_LONGITUDE));

		// invalid: latitude > 90
		assertArrayEquals(empty_hotel_array, boopingSite
				.getHotelsInCityByProximity(CITY_IN_DATABASE, OVER_90_LATITUDE, VALID_LONGITUDE));

		// invalid: latitude < (-90)
		assertArrayEquals(empty_hotel_array, boopingSite
				.getHotelsInCityByProximity(CITY_IN_DATABASE, BELOW_MINUS_90_LATITUDE, VALID_LONGITUDE));

		// invalid: longitude > 180
		assertArrayEquals(empty_hotel_array, boopingSite
				.getHotelsInCityByProximity(CITY_IN_DATABASE, VALID_LATITUDE, OVER_180_LONGITUDE));

		// invalid: longitude < (-180)
		assertArrayEquals(empty_hotel_array, boopingSite
				.getHotelsInCityByProximity(CITY_IN_DATABASE, VALID_LATITUDE, BELOW_MINUS_180_LONGITUDE));


		// --------------------- valid inputs ---------------------
		Hotel[] sorted_proximity_hotels_by_city = boopingSite
				.getHotelsInCityByProximity(CITY_IN_DATABASE, VALID_LATITUDE, VALID_LONGITUDE);

		// checking the number of hotels in sorted_proximity_hotels
		if (boopingSite == boopingSite_empty) {
			assertEquals(NUMBER_OF_HOTELS_IN_DATASET_EMPTY, sorted_proximity_hotels_by_city.length);

		} else if (boopingSite == boopingSite_one_city) {
			assertEquals(NUMBER_OF_HOTELS_IN_DATASET_ONE_CITY, sorted_proximity_hotels_by_city.length);
		}


		double last_distance = 0.0; // initialize to not important value
		int last_POIs_number = 0;
		boolean first_hotel = true;

		// moving across all returned hotels and check if their proximity and POIs are in the right order
		for (Hotel hotel : sorted_proximity_hotels_by_city) {
			// hotel is not from the given city
			assertEquals(CITY_IN_DATABASE, hotel.getCity());
			if (first_hotel) {
				last_distance = calculateDistance(hotel.getLatitude(), hotel.getLongitude());
				last_POIs_number = hotel.getNumPOI();
				first_hotel = false;
				continue;
			}

			double curr_distance = calculateDistance(hotel.getLatitude(), hotel.getLongitude());
			// current distance is smaller than lat distance
			assertFalse(curr_distance < last_distance);
			// if they have the same distance => check if curr number of POI is bigger than last POI number
			if (curr_distance == last_distance) {
				assertFalse(last_POIs_number < hotel.getNumPOI());
			}

			last_distance = curr_distance;
			last_POIs_number = hotel.getNumPOI();
		}

	}

}
<file_sep>/Ex6/src/CheckVariable.java
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * class to check a line of variable (declaration\assign)
 */
public class CheckVariable {

    // constants
    private static final String INT = "int";
    private static final String DOUBLE = "double";
    private static final String STRING = "String";
    private static final String BOOLEAN = "boolean";
    private static final String CHAR = "char";
    private static final String TRUE = "true";
    private static final String FALSE = "false";
    private static final String SPACE = " ";
    private static final String EMPTY_STRING = "";
    private static final String COMMA = ",";

    // Error messages
    private static final String ERROR_MESSAGE_TYPE_INVALID = "ERROR: type is invalid";
    private static final String ERROR_MESSAGE_NAME_INVALID = "ERROR: name format is invalid";
    private static final String ERROR_MESSAGE_NAME_IS_NULL = "ERROR: name is null";
    private static final String ERROR_MESSAGE_NOTHING_BETWEEN_COMMAS = "ERROR: nothing between commas";
    private static final String ERROR_MESSAGE_FINAL_MUST_BE_ASSIGN = "ERROR: final must be assigned";
    private static final String ERROR_MESSAGE_INVALID_TYPE = "ERROR: invalid type";
    private static final String ERROR_MESSAGE_VALUE_DOESNT_FIT_TYPE
            = "ERROR: value doesn't fit the variable type";
    private static final String ERROR_MESSAGE_VARIABLE_NOT_FOUND_OR_FINAL
            = "ERROR: variable not found or is final";
    private static final String ERROR_MESSAGE_2_VARIABLES_IN_SCOPE_WITH_SAME_NAME =
            "ERROR: 2 variables in the scope with the same name";
    private static final String ERROR_MESSAGE_VARIABLE_NOT_FOUND_OR_NOT_INITIALIZED_OR_ILLEGAL_VALUE =
            "ERROR: variable not found or not initialized or illegal value";
    private static final String ERROR_MESSAGE_VARIABLE_LINE_DOEST_MATCH_ANY_FORMAT =
            "ERROR: variable line doesn't match any possible format";


    /* regex of whitespace one or more times */
    private static final String REGEX_WHITESPACE = "\\s+";

    /* regex of whitespace one or more times in the beginning */
    private static final String REGEX_START_WHITESPACE = "^\\s+";

    /* regex of final in the beginning */
    private static final String REGEX_START_WHITESPACE_AND_FINAL = "^\\s*final\\s*";

    /* regex of name format */
    private static final String REGEX_NAME_FORMAT = "([a-zA-Z][\\w]*)|(_[\\w]+)";

    /* regex of string value format */
    private static final String REGEX_STRING_VALUE = "\"[^\\s\"',\\\\]*\"";

    /* regex of char value format */
    private static final String REGEX_CHAR_VALUE = "'[^\\s\"',\\\\]'";

    /* regex of "name = value ;"   (a = 3;) */
    private static final String REGEX_VARIABLE_STARTS_WITH_NAME
            = "\\s*(\\w+)\\s*=\\s*([^\\s,\\\\]+)\\s*;\\s*";

    /* regex of "name = value" without the ';' in the end  (a = 3) */
    private static final String REGEX_ASSIGN_VALUE_TO_VARIABLE = "\\s*(\\w+)\\s*=\\s*([^\\s,\\\\]+)\\s*";

    /* regex of 	"type name ;" 							(int a;)
          or 		"type name = value ;"					(int a = 3;)
           or		"type name1, name2, name 3; 			(int a, b, c;)
          or		"type name1, name2 = value, name 3; 	(int a,b = 3,c;) */
    private static final String REGEX_VARIABLE_STARTS_WITH_TYPE =
            "\\s*([a-zA-Z]+)\\s+(\\w+(\\s*=\\s*[^\\s,\\\\]+)?)" +
                    "\\s*(\\s*,\\s*\\w+(\\s*=\\s*[^\\s,\\\\]+)?\\s*)*;\\s*";

    /* regex of "final type name = value ;" 					(final int a = 3;)
            or    "final type name1 = value1, name2 = value2;"	(final int a = 1, b = 2;) */
    private static final String REGEX_VARIABLE_STARTS_WITH_FINAL =
            "\\s*final\\s+([a-zA-Z]+)\\s+(\\w+(\\s*=\\s*[^\\s,\\\\]+)?)" +
                    "\\s*(\\s*,\\s*\\w+(\\s*=\\s*[^\\s,\\\\]+)?\\s*)*;\\s*";


    private static final String[] ARRAY_TYPES = new String[]{INT, DOUBLE, BOOLEAN, STRING, CHAR};
    private static final List<String> validTypesList = Arrays.asList(ARRAY_TYPES);


    private static final Pattern patternVariableStartsWithName = Pattern
            .compile(REGEX_VARIABLE_STARTS_WITH_NAME);
    private static final Pattern patternVariableStartsWithType = Pattern
            .compile(REGEX_VARIABLE_STARTS_WITH_TYPE);
    private static final Pattern patternVariableStartsWithFinal = Pattern
            .compile(REGEX_VARIABLE_STARTS_WITH_FINAL);
    private static final Pattern patternAssignValueToVariable = Pattern
            .compile(REGEX_ASSIGN_VALUE_TO_VARIABLE);


    /**
     * check the format of the Name
     * @param str: given string of name
     * @throws InvalidPropertiesFormatException throws if format is invalid
     */
    public static void checkNameFormat(String str) throws InvalidPropertiesFormatException {
        if (str.matches(REGEX_NAME_FORMAT)) {
            return;
        }
        throw new InvalidPropertiesFormatException(ERROR_MESSAGE_NAME_INVALID);
    }


    /**
     * check if a given Value is in the right format for the given Type
     * @param type: given type
     * @param value: given value
     * @throws NumberFormatException: throws if value isn't int\double
     * @throws InvalidPropertiesFormatException: throws if one of the value doesn't match the other types
     */
    public static void checkValueAndTypeFormat(String type, String value)
            throws NumberFormatException, InvalidPropertiesFormatException {

        switch (type) {
            case INT:
                Integer.parseInt(value);
                return;

            case DOUBLE:
                Double.parseDouble(value);
                return;

            case STRING:
                if (value.matches(REGEX_STRING_VALUE)) {
                    return;
                }
                break;

            case BOOLEAN:
                if (value.equals(TRUE) || value.equals(FALSE)) {
                    return;
                }
                Double.parseDouble(value);
                return;

            case CHAR:
                if (value.matches(REGEX_CHAR_VALUE)) {
                    return;
                }
                break;
        }
        throw new InvalidPropertiesFormatException(ERROR_MESSAGE_VALUE_DOESNT_FIT_TYPE);
    }


    /**
     * check if the given string is a valid Type to assign into variable with assignType type
     * @param assignType: type of variable tried to assign with
     * @param varType: type of the variable to assign into
     * @throws InvalidPropertiesFormatException: throws if the types dont allow the given type
     */
    private static void checkAssignType(String assignType, String varType)
            throws InvalidPropertiesFormatException {
        // check if the found assigned type is valid to assign to the given type
        switch (varType) {
            case DOUBLE:
                if (assignType.equals(DOUBLE) || assignType.equals(INT)) {
                    return;
                }
                break;

            case BOOLEAN:
                if (assignType.equals(BOOLEAN) || assignType.equals(INT) || assignType.equals(DOUBLE)) {
                    return;
                }
                break;

            case INT:
                if (assignType.equals(INT)) {
                    return;
                }
                break;

            case STRING:
                if (assignType.equals(STRING)) {
                    return;
                }
                break;

            case CHAR:
                if (assignType.equals(CHAR)) {
                    return;
                }
                break;
        }
        throw new InvalidPropertiesFormatException(ERROR_MESSAGE_TYPE_INVALID);
    }


    /**
     * check the value - format and logical
     * @param type: type of the variable to assign into
     * @param value: value to assign with
     * @param thisScope: the current scope of the variable
     * @throws InvalidPropertiesFormatException: throws if the value assign is invalid
     */
    private static void checkValue(String type, String value, Scope thisScope)
            throws InvalidPropertiesFormatException {
        try {
            checkValueAndTypeFormat(type, value);
        }
        // value is not a legal value - so check if it is another variable name
        catch (NumberFormatException | InvalidPropertiesFormatException e) {
            Variable variableWithValueName = thisScope.findVariableInScopes(value);

            // check if the found variable exist and is initialized
            if (variableWithValueName != null && variableWithValueName.isInitialized()) {
                // if so - check if it's type is valid to the given type
                checkAssignType(variableWithValueName.getType(), type);
            } else { // if not found OR not initialized OR illegal value - throw
                // exception
                throw new InvalidPropertiesFormatException(
                        ERROR_MESSAGE_VARIABLE_NOT_FOUND_OR_NOT_INITIALIZED_OR_ILLEGAL_VALUE);
            }
        }
    }


    /**
     * check the name - format and logical
     * @param name: string of name to check
     * @param thisScope: the current scope
     * @throws InvalidPropertiesFormatException: throws if the name is invalid
     */
    private static void checkName(String name, Scope thisScope)
            throws InvalidPropertiesFormatException {
        checkNameFormat(name);
        // 2 variables with the same name in the same scope
        if (thisScope.getScopeVariables().containsKey(name)) {
            throw new InvalidPropertiesFormatException(ERROR_MESSAGE_2_VARIABLES_IN_SCOPE_WITH_SAME_NAME);
        }
    }


    /**
     * check the assign
     * @param name: name of variable
     * @param value: value to assign
     * @param type: type of the variable
     * @param thisScope: the current scope
     * @throws InvalidPropertiesFormatException: throws if the assign is invalid
     */
    private static void checkAssign(String name, String value, String type, Scope thisScope)
            throws InvalidPropertiesFormatException {
        if (name != null) {
            checkName(name, thisScope);
        } else {
            throw new InvalidPropertiesFormatException(ERROR_MESSAGE_NAME_IS_NULL);
        }
        checkValue(type, value, thisScope);
    }


    /**
     * check each variable in a line declaration - which starts with "final"
     * @param type: type declaration
     * @param thisScope: the current scope
     * @param splitByComma: string array of all the variables declarations
     * @param addVariableToScope: boolean if the variables need to be added to the scope or not
     * @throws InvalidPropertiesFormatException: throws if the declaration is invalid
     */
    private static void checkEachVarInDeclarationFinal(String type, Scope thisScope,
                                                       String[] splitByComma, boolean addVariableToScope)
            throws InvalidPropertiesFormatException {
        String name, value;
        Variable newVariable;
        Matcher matcher;
        for (String part : splitByComma) {
            if (part == null) {
                throw new InvalidPropertiesFormatException(ERROR_MESSAGE_NOTHING_BETWEEN_COMMAS);
            }

            matcher = patternAssignValueToVariable.matcher(part);
            if (matcher.matches()) { // with assign
                name = matcher.group(1);
                value = matcher.group(2);

                checkAssign(name, value, type, thisScope);
                if (thisScope.getParentScope() == null){ // global scope
                    newVariable = new Variable(type, name, true, true, true);
                }
                else{ // not global scope
                    newVariable = new Variable(type, name, true, true, false);
                }

            } else { // final must be assign in declaration
                throw new InvalidPropertiesFormatException(ERROR_MESSAGE_FINAL_MUST_BE_ASSIGN);
            }

            // if all good and need to add - add the new variable to this scope
            if (addVariableToScope) {
                thisScope.getScopeVariables().put(name, newVariable);
            }
        }
    }


    /**
     * check each variable in a line declaration - which doesnt starts with "final"
     * @param type: type declaration
     * @param thisScope: the current scope
     * @param splitByComma: string array of all the variables declarations
     * @param addVariableToScope: boolean if the variables need to be added to the scope or not
     * @throws InvalidPropertiesFormatException: throws if the declaration is invalid
     */
    private static void checkEachVarInDeclaration(String type, Scope thisScope,
                                                  String[] splitByComma, boolean addVariableToScope)
            throws InvalidPropertiesFormatException {
        String name, value = null;
        Variable newVariable;
        Matcher matcher;
        for (String part : splitByComma) {
            if (part == null) {
                throw new InvalidPropertiesFormatException(ERROR_MESSAGE_NOTHING_BETWEEN_COMMAS);
            }

            matcher = patternAssignValueToVariable.matcher(part);
            if (matcher.matches()) { // with assign
                name = matcher.group(1);
                value = matcher.group(2);

                checkAssign(name, value, type, thisScope);
                if (thisScope.getParentScope() == null){ // global scope
                    newVariable = new Variable(type, name, true, false, true);
                }
                else { // not global scope
                    newVariable = new Variable(type, name, true, false, false);
                }

            } else { // without assign
                name = part;
                checkName(name, thisScope);
                checkType(type);
                newVariable = new Variable(type, name, false, false, false);

            }

            // if all good and need to add - add the new variable to this scope
            if (addVariableToScope) {
                thisScope.getScopeVariables().put(name, newVariable);
            }
        }
    }


    /**
     * split by commas a given declaration line to the different variables parts assume there is nothing
     * before the type in the line
     * @param subLine: given line
     * @return string array of the different parts separated by commas
     */
    private static String[] splitVariablesByComma(String subLine) {
        // find first space (must be after type)
        int indexOfFirstSpaceAfterType = subLine.indexOf(SPACE);
        // take only the part of: "a" \ "a - 3" \ "a, b, c" \ "a, b = 3, c" (remove type part)
        subLine = subLine.substring(indexOfFirstSpaceAfterType + 1, subLine.lastIndexOf(";"));

        // remove all spaces
        subLine = subLine.replaceAll(REGEX_WHITESPACE, EMPTY_STRING);
        // split by ','
        return subLine.split(COMMA);
    }


    /**
     * check if the type is one of the valid types
     * @param type: given string to check
     * @throws InvalidPropertiesFormatException: throws if it's not one of the possible types
     */
    private static void checkType(String type) throws InvalidPropertiesFormatException {
        if (validTypesList.contains(type)){
            return;
        }
        throw new InvalidPropertiesFormatException(ERROR_MESSAGE_INVALID_TYPE);
    }

    /**
     * check just if the format of the line is a match to a valid variable possible line
     * @param line: given string of a line
     * @return: true if the line match one of the possible formats and false otherwise
     */
    public static boolean checkJustFormat(String line) {
        Matcher matcher = patternVariableStartsWithName.matcher(line);
        if (matcher.matches()) {
            return true;
        }
        matcher = patternVariableStartsWithType.matcher(line);
        if (matcher.matches()) {
            return true;
        }
        matcher = patternVariableStartsWithFinal.matcher(line);
        return matcher.matches();
    }


    /**
     * check a line manipulating variables (declaration/assign)
     * @param line: given string of a line
     * @param thisScope: the current scope of the line
     * @param addVariableToScope: boolean if the variables need to be added to the scope or not
     * @throws InvalidPropertiesFormatException: throws if something went wrong
     * @throws NumberFormatException: throws if number assign went wrong
     */
    public static void checkVariableLine(String line, Scope thisScope, boolean addVariableToScope)
            throws InvalidPropertiesFormatException, NumberFormatException {

        // Variable starts with Name - (a = 3;)
        Matcher matcher = patternVariableStartsWithName.matcher(line);
        if (matcher.matches()) {
            String name = matcher.group(1);
            String value = matcher.group(2);

            checkNameFormat(name);
            Variable variableWithGivenName = thisScope.findVariableInScopes(name);

            // if a variable with such name exist and it's not final
            if ((variableWithGivenName != null) && (!variableWithGivenName.isFinal())) {
                checkValue(variableWithGivenName.getType(), value, thisScope);
            } else {
                throw new InvalidPropertiesFormatException(ERROR_MESSAGE_VARIABLE_NOT_FOUND_OR_FINAL);
            }
            variableWithGivenName.setInitialized();
            if (thisScope.getParentScope() == null){ // global scope
                variableWithGivenName.setIsGlobalInitialized();
            }
            return;
        }

        // Variable starts with Type - (int a;) or (int a = 3;) or (int a, b, c;) or (int a,b = 3,c;)
        matcher = patternVariableStartsWithType.matcher(line);
        if (matcher.matches()) {
            String type = matcher.group(1);

            // remove all beginning whitespaces
            String subLine = line.replaceAll(REGEX_START_WHITESPACE, EMPTY_STRING);
            // split by comma
            String[] splitByComma = splitVariablesByComma(subLine);

            checkEachVarInDeclaration(type, thisScope, splitByComma, addVariableToScope);
            return;
        }


        // Variable starts with final - (final int a;)
        matcher = patternVariableStartsWithFinal.matcher(line);
        if (matcher.matches()) {
            String type = matcher.group(1);

            // remove all beginning whitespaces and final
            String subLine = line.replaceAll(REGEX_START_WHITESPACE_AND_FINAL, EMPTY_STRING);
            // split by comma
            String[] splitByComma = splitVariablesByComma(subLine);

            checkEachVarInDeclarationFinal(type, thisScope, splitByComma, addVariableToScope);
            return;
        }

        // line doesn't match any of the possible variable-line formats
        throw new InvalidPropertiesFormatException(ERROR_MESSAGE_VARIABLE_LINE_DOEST_MATCH_ANY_FORMAT);
    }

}<file_sep>/Ex3/src/RatingCompare.java
import oop.ex3.searchengine.Hotel;

import java.util.Comparator;


/**
 * implementation of hotels rating star compare class
 */
public class RatingCompare implements Comparator<Hotel> {


	/** representing bigger return value in comparator */
	private static final int BIGGER = 1;

	/** representing smaller return value in comparator */
	private static final int SMALLER = (-1);


	/**
	 * @param hotel1: hotel object
	 * @param hotel2: hotel object
	 * @return 1 if hotel1's star rating is bigger, (-1) if hotel1's star rating is smaller. if the two
	 * 		hotels have the same star rating it will compare between their names with String.compareTo()
	 */
	public int compare(Hotel hotel1, Hotel hotel2) {
		if (hotel1.getStarRating() < hotel2.getStarRating()) {
			return SMALLER;
		}
		if (hotel1.getStarRating() > hotel2.getStarRating()) {
			return BIGGER;
		}
		return hotel1.getPropertyName().compareTo(hotel2.getPropertyName());
	}

}
<file_sep>/Ex5/src/filesprocessing/DirectoryProcessor.java
package filesprocessing;


import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;

import static filesprocessing.Errors.*;
import static filesprocessing.Filter.*;
import static filesprocessing.Order.*;
import static filesprocessing.Output.*;

/**
 * class implementation of DirectoryProcessor
 */
public class DirectoryProcessor {


	/** Error message of invalid number of arguments */
	protected static final String ERROR_MESSAGE_NOT_2_ARGS
			= "ERROR: invalid usage - didnt receive 2 arguments";

	/** Error message of invalid arguments */
	protected static final String ERROR_MESSAGE_INVALID_ARGS = "ERROR: invalid arguments";

	/** Error message of I/O problems */
	protected static final String ERROR_MESSAGE_IO_PROBLEM = "ERROR: I/O problems";

	/** Error message of missing sub-section */
	protected static final String ERROR_MESSAGE_MISSING_SUBSECTION_NAME = "ERROR: Missing subsection";

	/** Error message of bad sub-section name or missing sub-section */
	protected static final String ERROR_MESSAGE_BAD_OR_MISSING_SUBSECTION_NAME = "ERROR: Bad subsection " +
																				 "name";

	/** name of filter sub-section */
	protected static final String FILTER_SECTION_NAME = "FILTER";

	/** name of order sub-section */
	protected static final String ORDER_SECTION_NAME = "ORDER";

	/** number of the max lines distance between two sub-sections */
	protected static final int MAX_LINES_BETWEEN_SUBSECTIONS = 2;

	/** the separator between the filter line parts */
	protected static final String SEPARATOR_IN_LINE = "#";

	/** first line in a section */
	protected static final int FIRST_LINE = 1;

	/** second line in a section */
	protected static final int SECOND_LINE = 2;

	/** fourth line in a section */
	protected static final int FOURTH_LINE = 4;


	protected static String commandsFilePath;
	protected static String sourceDirPath;
	protected static File sourceDir;
	protected static File commandsFile;
	protected static Scanner fileScanner;
	protected static ArrayList<File> filtered_files = null;


	/**
	 * return a Scanner of the commands file
	 * @return Scanner of the commands file
	 * @throws IOException: if there was an error with accessing the file
	 */
	protected static Scanner getFileScanner() throws IOException {
		try {
			return new Scanner(commandsFile);
		} catch (IOException ioe) { // I/O problems
			System.err.println(ERROR_MESSAGE_IO_PROBLEM);
			throw new IOException();
		}
	}


	/**
	 * process the commands file to filter and order as written inside
	 * @param fileScanner: Scanner of the Commands file
	 */
	private static void processCommandsFile(Scanner fileScanner) {
		int line_in_section = 1;
		int line_counter = 1;
		String curr_line;
		boolean finished_section = false;
		boolean last_was_ORDER = false;

		while (fileScanner.hasNext()) { // every row
			curr_line = fileScanner.nextLine();

			switch (curr_line) {

			case FILTER_SECTION_NAME:
				if (line_in_section ==
					SECOND_LINE) { // last ORDER didnt have an order-name line - sort by abs
					filtered_files = filterFiles(curr_line, sourceDir, line_counter);
				}
				// when the section has only 3 lines so the 4th line is actually a new FILTER line
				if (line_in_section == FOURTH_LINE) {
					finished_section = true;
					line_in_section = FIRST_LINE;
				}
				break;

			case ORDER_SECTION_NAME:
				// sort-by ABS in case that's the last row in the file and obviously has no order-name
				if (line_in_section == FOURTH_LINE) {
					orderFiles(curr_line, filtered_files, line_counter);
					break;
				}
				// in case ORDER was instead of a filter-name line
				if (line_in_section == SECOND_LINE) {
					filtered_files = filterFiles(curr_line, sourceDir, line_counter);
					break;
				}
				orderFiles(ABS, filtered_files, line_counter);
				last_was_ORDER = true;
				break;

			default: // if not a title line
				if (line_in_section == SECOND_LINE) { // filter-name line
					filtered_files = filterFiles(curr_line, sourceDir, line_counter);

				} else if (line_in_section == FOURTH_LINE) { // order-name line
					orderFiles(curr_line, filtered_files, line_counter);
					finished_section = true;
					last_was_ORDER = false;
				}
				break;
			}
			line_in_section++;

			if (finished_section) {
				if (!curr_line.equals(FILTER_SECTION_NAME)) {
					line_in_section = FIRST_LINE;
				}
				printSortedFiles(); // Print files
				finished_section = false;
			}

			line_counter++;
		}
		if (last_was_ORDER) {
			printSortedFiles(); // Print files
		}
	}


	/**
	 * main method
	 * @param args: list of Strings where args[0] is sourceDir path and args[1] is Commands File path
	 */
	public static void main(String[] args) {

		try {
			if (args.length != 2) { // Type 2 error - not 2 arguments
				throw new IllegalArgumentException();
			}

			commandsFilePath = args[1];
			sourceDirPath = args[0];
			sourceDir = new File(args[0]);
			commandsFile = new File(commandsFilePath);

			// Type 2 Errors
			foundType2Error();

			// Filter and Order the files
			fileScanner = getFileScanner();

		} catch (IllegalArgumentException exception) {
			System.err.println(ERROR_MESSAGE_NOT_2_ARGS);
			return;
		}
		// Error messages already printed in the methods
		catch (RuntimeException exception) {
			return;
		} catch (IOException ioe) {
			System.err.println(ERROR_MESSAGE_IO_PROBLEM);
			return;
		}

		processCommandsFile(fileScanner);

		fileScanner.close();
	}
}
<file_sep>/Ex6/src/CheckMethod.java
import java.util.HashMap;
import java.util.InvalidPropertiesFormatException;
import java.util.LinkedList;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Checking the method code validity
 */
public class CheckMethod {
    private static final String ERROR_MESSAGE_METHOD_DUPLICATE = "ERROR: Methods must have different names";
    private static final String ERROR_MESSAGE_METHOD_RETURN = "ERROR: Methods must end with return; line " +
            "followed by a closing curly bracket line";
    private static final String OPEN_CURLY_BRACKET = "{";
    private static final String NEW_LINE = "\n";
    static final String REGEX_CLOSE_CURLY_BRACKET = "^\\s*\\}\\s*$";
    static final String REGEX_OPEN_CURLY_BRACKET_END = "^[\\s\\S]*\\{\\s*$";
    static final String REGEX_SIGNATURE_FORMAT = "^\\s*\\bvoid\\b\\s+[a-zA-Z][\\w]*\\s*\\(\\s*(((\\s*final\\s+)" +
        "?(String|boolean|char|int|double)\\s+(([a-zA-Z][\\w]*)|(_[\\w]+))\\s*(\\)|(\\s*,\\s*(\\s*final\\s+)?" +
        "(String|boolean|char|int|double)\\s+(([a-zA-Z][\\w]*)|(_[\\w]+))\\s*)*\\s*\\)))|(\\s*\\)\\s*))\\s*\\{\\s*$";
    static final String REGEX_SIGNATURE_FIND = "\\bvoid\\b\\s+[a-zA-Z][\\w]*\\s*\\(\\s*(((\\s*final\\s+)" +
            "?(String|boolean|char|int|double)\\s+(([a-zA-Z][\\w]*)|(_[\\w]+))\\s*(\\)|(\\s*,\\s*(\\s*final\\s+)?" +
            "(String|boolean|char|int|double)\\s+(([a-zA-Z][\\w]*)|(_[\\w]+))\\s*)*\\s*\\)))|(\\s*\\)\\s*))\\s*\\{\\s*";
    static final String REGEX_SIGNATURE_LAYOUT = "\\s*\\S+\\s+\\S+\\s*\\([\\s\\S]*\\)\\s*\\{\\s*";
    static final String REGEX_PARAMETER = "(final\\s+)?(String|boolean|char|int|double)\\s+" +
            "(([a-zA-Z][\\w]*)|(_[\\w]+))";
    static final String REGEX_METHOD_NAME = "void\\b\\s+([a-zA-Z][\\w]*)\\s*\\(";
    static final String REGEX_RETURN = "^\\s*return\\s*;\\s*$";
    static final int FINAL_PARAM_FIELDS = 3;

    private static String lastMethodCode;

    /**
     * Checking validity of method's signature by regex
     * @param line
     * @return
     */
    public static boolean isValidMethodSignature(String line){
        return line.matches(REGEX_SIGNATURE_FORMAT);
    }

    /**
     * Checking for a method's signature by regex (not strict)
     * @param line
     * @return
     */
    public static boolean isMethodSignatureLayout(String line){
        return line.matches(REGEX_SIGNATURE_LAYOUT);
    }

    /**
     * Creating a String array out of the method's signature line to hold the parameters
     * @param line
     * @return
     */
    public static String[] getParameterVariablesLines(String line){
        Matcher m = Pattern.compile(REGEX_PARAMETER).matcher(line);
        String variables = "";

        while (m.find()) {
            variables += m.group() + ";" + NEW_LINE;
        }

        if(variables.isEmpty()){
            return null;
        }

        return variables.substring(0, variables.lastIndexOf(NEW_LINE)).split(NEW_LINE);
    }

    /**
     * Creating a Variable array out of the method's signature line to hold the parameters
     * @param line
     * @return
     */
    public static Variable[] getParameterVariables(String line){
        Matcher m = Pattern.compile(REGEX_PARAMETER).matcher(line);
        LinkedList<Variable> varLines = new LinkedList<>();

        while (m.find()) {
            String parameter = m.group();
            String[] parameterFields = parameter.split("\\s+");

            boolean isFinal = false;
            String varName = parameterFields[1];
            String varType = parameterFields[0];

            if(parameterFields.length == FINAL_PARAM_FIELDS){
                isFinal = true;
                varName = parameterFields[2];
                varType = parameterFields[1];
            }

            varLines.add(new Variable(varType, varName, true, isFinal, false));
        }

        return varLines.toArray(new Variable[varLines.size()]);
    }

    /**
     * Finding methods in the code and checking for duplicates/no return at the end etc
     * @param code
     * @return
     * @throws InvalidPropertiesFormatException
     */
    public static HashMap<String, Method> findMethods(String code) throws InvalidPropertiesFormatException {
        HashMap<String, Method> methods = new HashMap<>();
        Matcher methodMatcher = Pattern.compile(REGEX_SIGNATURE_FIND).matcher(code);

        while (methodMatcher.find()) {
            String currMethod = methodMatcher.group();
            if(isReturnEnd(code, currMethod, methodMatcher.end())) {
                Variable[] methodParams = getParameterVariables(currMethod);

                Matcher methodNameMatcher = Pattern.compile(REGEX_METHOD_NAME).matcher(currMethod);
                methodNameMatcher.find();
                String methodName = methodNameMatcher.group(1);

                if (methods.containsKey(methodName)) {
                    throw new InvalidPropertiesFormatException(ERROR_MESSAGE_METHOD_DUPLICATE);
                } else {
                    methods.put(methodName, new Method(methodName, methodParams, lastMethodCode));
                }
            }
            else{
                throw new InvalidPropertiesFormatException(ERROR_MESSAGE_METHOD_RETURN);
            }
        }

        return methods;
    }

    /**
     * Checking that there is a return statement at the end of the method's code
     * (Also getting the method's code along the search)
     * @param code
     * @param signature
     * @param startIndex
     * @return
     */
    public static boolean isReturnEnd(String code,String signature, int startIndex){
        Stack<String> stack = new Stack<>();
        stack.push(OPEN_CURLY_BRACKET);
        String[] lines = code.substring(startIndex).split(NEW_LINE);
        String prevCodeLine = "";
        int currIndex = 0;
        String methodCode = signature;

        while(!stack.isEmpty()){
            if(lines[currIndex].matches(REGEX_OPEN_CURLY_BRACKET_END)){
                stack.push(OPEN_CURLY_BRACKET);
            }
            else if(lines[currIndex].matches(REGEX_CLOSE_CURLY_BRACKET)){
                stack.pop();

                if(!stack.isEmpty()){
                    prevCodeLine = lines[currIndex];
                }
            }
            else{
                prevCodeLine = lines[currIndex];
            }

            methodCode += lines[currIndex] + NEW_LINE;
            currIndex++;
        }

        lastMethodCode = methodCode.substring(0, methodCode.lastIndexOf(NEW_LINE));
        return prevCodeLine.matches(REGEX_RETURN);
    }
}
<file_sep>/Ex5/src/test/java/python_tests/readable_files.py
import subprocess

if __name__ == '__main__':
    schoolOutput = open("C:\\Users\\24565\\PycharmProjects\\javaTest"
                        "\\tester_files\\tests\\zzz-test-by-school_filter054"
                        ".flt\\complex_school_solution_output.txt")
    schoolOutputContent = {x.strip() for x in schoolOutput}
    schoolOutput.close()
    avishaiOutput = open("C:\\Users\\24565\\PycharmProjects\\javaTest"
                         "\\tester_files\\tests\\test03\\complex_user_output"
                         ".txt")
    avOutputContent = {x.strip() for x in avishaiOutput}
    needToBeRead = set()
    for item in avOutputContent:
        if item not in schoolOutputContent:
            command_list = ["attrib" ,"+R",
                            "C:\\Users\\24565\\PycharmProjects\\javaTest"
                            "\\tester_files\\files_to_filter\\complex"
                            ""+"\\" + item]
            process = subprocess.Popen(command_list, stdin=subprocess.PIPE,
                             stdout=subprocess.PIPE, stderr=subprocess.PIPE,
                             universal_newlines=True)
            process.communicate()<file_sep>/Ex4/src/SingleLinkedList.java
import java.util.LinkedList;


/**
 * Wrapper class of a LinkedList<String>
 */
public class SingleLinkedList extends LinkedList<String> {

	LinkedList<String> list;

	/**
	 * constructor of the class
	 */
	SingleLinkedList(){
		list = new LinkedList<String>();
	}


	/**
	 * Inserts the specified element at the beginning of this list.
	 *
	 * @param newValue the string to add
	 */
	public void addValue(String newValue){
		list.addFirst(newValue);
	}


	/**
	 * Returns true iff this list contains at least one element of the given string
	 *
	 * @param searchVal string whose presence in this list is to be tested
	 * @return true if this list contains the specified element and false otherwise
	 */
	public boolean contains(String searchVal){
		return list.contains(searchVal);
	}


	/**
	 * Removes the element with the lowest index of the element if such an element exists
	 *
	 * @param toDelete string to be removed from this list, if present
	 */
	public void remove(String toDelete){
		list.remove(toDelete);
	}


	/**
	 * @return the linked list of this instance
	 */
	public LinkedList<String> getList(){ return list; }
}
<file_sep>/Ex4/src/SimpleHashSet.java

/**
 * abstract class implementing SimpleSet Just the size method is being implemented and the other methods are
 * implemented in subclasses to their use
 */
abstract class SimpleHashSet implements SimpleSet {

	/** no elements in the HashSet */
	protected static final int NO_ELEMENTS = 0;

	/** default initial capacity of the HashSet */
	protected static final int DEFAULT_INIT_CAPACITY = 16;

	/** default initial upperLoadFactor of the HashSet */
	protected static final float DEFAULT_INIT_UPPER_LOAD_FACTOR = 0.75f;

	/** default initial lowerLoadFactor of the HashSet */
	protected static final float DEFAULT_INIT_LOWER_LOAD_FACTOR = 0.25f;

	/** representing an increase size */
	protected static final int INCREASE_SIZE = 1;

	/** representing a decrease size */
	protected static final int DECREASE_SIZE = (-1);


	protected int numOfElements;
	protected int capacity;
	protected float upperLoadFactor;
	protected float lowerLoadFactor;

	/**
	 * constructor of SimpleHashSet
	 */
	SimpleHashSet() {
		numOfElements = NO_ELEMENTS;
		capacity = DEFAULT_INIT_CAPACITY;
		upperLoadFactor = DEFAULT_INIT_UPPER_LOAD_FACTOR;
		lowerLoadFactor = DEFAULT_INIT_LOWER_LOAD_FACTOR;
	}


	/**
	 * @return The number of elements currently in the set
	 */
	@Override
	public int size() { return numOfElements; }


	/**
	 * @return The current capacity (number of cells) of the table.
	 */
	public int capacity() { return capacity; }


	/**
	 * @return the load factor - current number of elements in the hash divided by the capacity
	 */
	protected float loadFactor() { return ((float) numOfElements / (float) capacity);}


	/**
	 * resizing the hash according to the given type type=1 : increase , type=(-1): decrease
	 * @param type: int of which resize type to apply
	 */
	abstract void resize(int type);

}
