<commit_before>part of entity;

@app.Group("/entities")
class EntityEndpoint {
	@app.Route("/list")
	List<Map<String, dynamic>> allEntities(@app.QueryParam("token") String token) {
		if (token != redstoneToken) {
			return [{"error": "true"}, {"token": "invalid"}];
		}

		if (cachedData == null) {
			List<Map<String, dynamic>> result = new List();
			entities.forEach((Type type) => result.add(aboutEntity(type.toString())));
			cachedData = result;
			return result;
		} else {
			return cachedData;
		}
	}

	static Map<String, dynamic> aboutEntity(dynamic entity) {
		if (entity is String) {
			try {
				entity = findByName(entity.trim());
			} catch(_) {
				return null;
			}
		}
		if (entity is! Entity) {
			return null;
		}

		ClassMirror mirror = findClassMirror(entity.runtimeType.toString());

		Map<String, dynamic> map = new Map()
			..["id"] = entity.runtimeType.toString()
			..["name"] = splitCamelCase(entity.runtimeType.toString())
			..["responses"] = entity.responses;

		if (entity.runtimeType == NPC) {
			map["name"] = entity.type;
		}

		if (mirror.isSubclassOf(findClassMirror("Vendor"))) {
			map
				..["category"] = "Vendor"
				..["sellItems"] = new List();
			if (entity.itemsPredefined) {
				entity.itemsForSale.forEach((Map item) => map["sellItems"].add(item["itemType"]));
			}
		}

		if (mirror.isSubclassOf(findClassMirror("Shrine"))) {
			map["category"] = "Shrine";
		}

		if (mirror.isSubclassOf(findClassMirror("Tree"))) {
			map["category"] = "Tree";
		} else if (mirror.isSubclassOf(findClassMirror("Rock"))) {
			map["category"] = "Rock";
		} else if (mirror.isSubclassOf(findClassMirror("Plant"))) {
			map["category"] = "Plant";
		}

		if (entity.states != null) {
			map
				..["currentState"] = entity.currentState.stateName
				..["states"] = new List();
			entity.states.values.forEach((Spritesheet state) => map["states"].add(state.toMap()));
		}

		return map;
	}

	/// This method is awful.
	static Entity findByName(String entityClassName) {
		ClassMirror mirror = findClassMirror(entityClassName);

		dynamic _construct(int attempt) {
			// Call the default constructor with attempt number of null values
			List args = new List.filled(attempt, null);
			return mirror
				.newInstance(new Symbol(""), args)
				.reflectee;
		}

		try {
			// Fake vendor constructors have 0 arguments
			return _construct(0);
		} catch(_) {
			try {
				// Most entity constructors have 4 arguments
				return _construct(4);
			} catch(_) {
				// Some entity constructors have 5 arguments
				return _construct(5);
			}
		}
	}

	static final List<Type> entities = [
		// NPCs
		Auctioneer, Crab, DustTrap, Mailbox, VisitingStone,
		// NPCs -> Animals
		Batterfly, Butterfly, Chicken, Firefly, HeliKitty, Piggy, Salmon,
		// NPCs -> Shrines
		Alph, AlphFirebog, AlphIx, AlphUralia,
		Cosma, CosmaFirebog, CosmaIx, CosmaUralia,
		Friendly, FriendlyFirebog, FriendlyIx, FriendlyUralia,
		Grendaline, GrendalineFirebog, GrendalineIx, GrendalineUralia,
		Humbaba, HumbabaFirebog, HumbabaIx, HumbabaUralia,
		Lem, LemFirebog, LemIx, LemUralia,
		Mab, MabFirebog, MabIx, MabUralia,
		Pot, PotFirebog, PotIx, PotUralia,
		Spriggan, SprigganFirebog, SprigganIx, SprigganUralia,
		Tii, TiiFirebog, TiiIx, TiiUralia,
		Zille, ZilleFirebog, ZilleIx, ZilleUralia,
		// NPCs -> Vendors
		Helga, UncleFriendly, MealVendor, SnoConeVendingMachine,
		StreetSpiritFirebog, StreetSpiritGroddle, StreetSpiritZutto,
		ToolVendor,
		AlchemicalVendor, AnimalVendor, GardeningVendor, GroceriesVendor,
		HardwareVendor, KitchenVendor, MiningVendor, ProduceVendor, ToyVendor,
		// Plants
		DirtPile, HellGrapes, IceNubbin, Jellisac, MortarBarnacle, PeatBog,
		// Plants -> Rocks
		BerylRock, DulliteRock, MetalRock, SparklyRock,
		// Plants -> Trees<commit_msg>add foxes to entity endpoint (wiki)<commit_after>part of entity;

@app.Group("/entities")
class EntityEndpoint {
	@app.Route("/list")
	List<Map<String, dynamic>> allEntities(@app.QueryParam("token") String token) {
		if (token != redstoneToken) {
			return [{"error": "true"}, {"token": "invalid"}];
		}

		if (cachedData == null) {
			List<Map<String, dynamic>> result = new List();
			entities.forEach((Type type) => result.add(aboutEntity(type.toString())));
			cachedData = result;
			return result;
		} else {
			return cachedData;
		}
	}

	static Map<String, dynamic> aboutEntity(dynamic entity) {
		if (entity is String) {
			try {
				entity = findByName(entity.trim());
			} catch(_) {
				return null;
			}
		}
		if (entity is! Entity) {
			return null;
		}

		ClassMirror mirror = findClassMirror(entity.runtimeType.toString());

		Map<String, dynamic> map = new Map()
			..["id"] = entity.runtimeType.toString()
			..["name"] = splitCamelCase(entity.runtimeType.toString())
			..["responses"] = entity.responses;

		if (entity.runtimeType == NPC) {
			map["name"] = entity.type;
		}

		if (mirror.isSubclassOf(findClassMirror("Vendor"))) {
			map
				..["category"] = "Vendor"
				..["sellItems"] = new List();
			if (entity.itemsPredefined) {
				entity.itemsForSale.forEach((Map item) => map["sellItems"].add(item["itemType"]));
			}
		}

		if (mirror.isSubclassOf(findClassMirror("Shrine"))) {
			map["category"] = "Shrine";
		}

		if (mirror.isSubclassOf(findClassMirror("Tree"))) {
			map["category"] = "Tree";
		} else if (mirror.isSubclassOf(findClassMirror("Rock"))) {
			map["category"] = "Rock";
		} else if (mirror.isSubclassOf(findClassMirror("Plant"))) {
			map["category"] = "Plant";
		}

		if (entity.states != null) {
			map
				..["currentState"] = entity.currentState.stateName
				..["states"] = new List();
			entity.states.values.forEach((Spritesheet state) => map["states"].add(state.toMap()));
		}

		return map;
	}

	/// This method is awful.
	static Entity findByName(String entityClassName) {
		ClassMirror mirror = findClassMirror(entityClassName);

		dynamic _construct(int attempt) {
			// Call the default constructor with attempt number of null values
			List args = new List.filled(attempt, null);
			return mirror
				.newInstance(new Symbol(""), args)
				.reflectee;
		}

		try {
			// Fake vendor constructors have 0 arguments
			return _construct(0);
		} catch(_) {
			try {
				// Most entity constructors have 4 arguments
				return _construct(4);
			} catch(_) {
				// Some entity constructors have 5 arguments
				return _construct(5);
			}
		}
	}

	static final List<Type> entities = [
		// NPCs
		Auctioneer, Crab, DustTrap, Mailbox, VisitingStone,
		// NPCs -> Animals
		Batterfly, Butterfly, Chicken, Firefly, Fox, HeliKitty, Piggy, Salmon, SilverFox,
		// NPCs -> Shrines
		Alph, AlphFirebog, AlphIx, AlphUralia,
		Cosma, CosmaFirebog, CosmaIx, CosmaUralia,
		Friendly, FriendlyFirebog, FriendlyIx, FriendlyUralia,
		Grendaline, GrendalineFirebog, GrendalineIx, GrendalineUralia,
		Humbaba, HumbabaFirebog, HumbabaIx, HumbabaUralia,
		Lem, LemFirebog, LemIx, LemUralia,
		Mab, MabFirebog, MabIx, MabUralia,
		Pot, PotFirebog, PotIx, PotUralia,
		Spriggan, SprigganFirebog, SprigganIx, SprigganUralia,
		Tii, TiiFirebog, TiiIx, TiiUralia,
		Zille, ZilleFirebog, ZilleIx, ZilleUralia,
		// NPCs -> Vendors
		Helga, UncleFriendly, MealVendor, SnoConeVendingMachine,
		StreetSpiritFirebog, StreetSpiritGroddle, StreetSpiritZutto,
		ToolVendor,
		AlchemicalVendor, AnimalVendor, GardeningVendor, GroceriesVendor,
		HardwareVendor, KitchenVendor, MiningVendor, ProduceVendor, ToyVendor,
		// Plants
		DirtPile, HellGrapes, IceNubbin, Jellisac, MortarBarnacle, PeatBog,
		// Plants -> Rocks
		BerylRock, DulliteRock, MetalRock, SparklyRock,
		// Plants -> Trees
{'fraction_non_alphanumeric': 0.14206642066420663, 'fraction_numerical': 0.0015814443858724301, 'mean_word_length': 4.086461126005362, 'pattern_counts': {'":': 4, '<': 17, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4990707', 'n_tokens_mistral': 3116, 'n_tokens_neox': 2670, 'n_words': 576}