From 86adc973a2c83aec9bb06362487c001643fbeb1e Mon Sep 17 00:00:00 2001 From: Clemens Klug Date: Mon, 7 Oct 2019 17:20:23 +0200 Subject: [PATCH] add oeb-new config --- analysis/analyzers/__init__.py | 4 +- analysis/analyzers/analyzer/biogames.py | 113 ++++++++++++++++++++++++ analysis/analyzers/render/__init__.py | 9 ++ analysis/analyzers/render/biogames.py | 67 +++++++++++++- analysis/analyzers/render/default.py | 22 +++-- analysis/util/geo.py | 20 +++-- analysis/util/meta_temp.py | 73 ++++++++++++++- analysis/util/output.py | 15 ++++ selector/config.py | 76 +++++++++++++++- tasks/tasks.py | 37 ++++---- 10 files changed, 400 insertions(+), 36 deletions(-) create mode 100644 analysis/util/output.py diff --git a/analysis/analyzers/__init__.py b/analysis/analyzers/__init__.py index 8446baf..1c6cb74 100644 --- a/analysis/analyzers/__init__.py +++ b/analysis/analyzers/__init__.py @@ -3,7 +3,7 @@ from typing import List from .analyzer import Analyzer, Result from .analyzer.biogames import BoardDurationAnalyzer, SimulationRoundsAnalyzer, ActivationSequenceAnalyzer, \ BiogamesCategorizer, ActivityMapper, BiogamesStore, InstanceConfig, SimulationOrderAnalyzer, SimulationCategorizer, \ - SimulationFlagsAnalyzer, GameField_InstanceCategorizer + SimulationFlagsAnalyzer, GameField_InstanceCategorizer, BiogamesTasks, BiogamesDuration, GameFieldInstanceGroup from .analyzer.default import LogEntryCountAnalyzer, LocationAnalyzer, LogEntrySequenceAnalyzer, ActionSequenceAnalyzer, \ CategorizerStub, Store, ProgressAnalyzer, SimpleCategorizer, WhitelistAnalyzer from .analyzer.locomotion import LocomotionActionAnalyzer, CacheSequenceAnalyzer @@ -15,7 +15,7 @@ from .render.default import PrintRender, JSONRender, TrackRender, HeatMapRender, LogEntryCountCSV, KMLRender, GeoJSON from .render.locomotion import LocomotionActionRelativeRender, LocomotionActionAbsoluteRender, \ LocomotionActionRatioRender -from .render.wip import get_all_data, plot_time_space_rel +#from .render.wip import get_all_data, plot_time_space_rel __FALLBACK__ = PrintRender __MAPPING__ = { diff --git a/analysis/analyzers/analyzer/biogames.py b/analysis/analyzers/analyzer/biogames.py index 3edc637..970cb62 100644 --- a/analysis/analyzers/analyzer/biogames.py +++ b/analysis/analyzers/analyzer/biogames.py @@ -150,6 +150,31 @@ class GameField_InstanceCategorizer(CategorizerStub): # TODO: refactor return False +class GameFieldInstanceGroup(Analyzer): + __name__ = "BiogamesGamefieldInstanceGroupAnalizer" + + def __init__(self, settings: LogSettings): + super().__init__(settings) + self.metadata = None + + def process(self, entry: dict) -> bool: + if not self.metadata: + if entry[self.settings.type_field] in self.settings.custom['instance_start']: + try: + self.metadata = {"instance_config_id": json_path(entry, self.settings.custom['instance_config_id']), + "instance_id": entry[self.settings.custom['instance_id']], + "timestamp": str(entry["timestamp"]), + "player_group_name": entry['player_group_name'] + } + except KeyError as e: + print(entry) + raise e + return False + + def result(self, store: ResultStore, **kwargs) -> None: + store.add(Result(type(self), self.metadata)) + + class ActivityMapper(Analyzer): __name__ = "ActivityMapper" classes = { @@ -287,6 +312,94 @@ class ActivityMapper(Analyzer): return {"type": "Feature", "geometry": {"type": "LineString", "coordinates": []}, "properties": {'start_timestamp': timestamp, 'coordTimes': []}} +class BiogamesDuration(Analyzer): + __name__ = "BiogamesDuration" + + def __init__(self, settings: LogSettings) -> None: + super().__init__(settings) + self.first = None + self.last = None + self.sequences = defaultdict(list) + self.filters = SimpleNamespace() + self.filters.start = lambda entry: combinate(self.settings.custom["sequences2"]["start"], entry) + self.filters.end = lambda entry: combinate(self.settings.custom["sequences2"]["end"], entry) + self.sequence = None + self.sequence_start = None + self.cache = "None" + + def process(self, entry: dict) -> bool: + if not self.first: + self.first = entry['timestamp'] + self.last = entry['timestamp'] + if not self.sequence and self.filters.start(entry): + self.sequence = entry['sequence_id'] + self.sequence_start = entry['timestamp'] + elif self.sequence and self.filters.end(entry): + self.sequences[f"{self.cache}+{self.sequence}"].append((self.sequence_start, entry['timestamp'])) + self.sequences[f"only+{self.sequence}"].append((self.sequence_start, entry['timestamp'])) + self.sequence = None + self.sequence_start = 0 + self.cache = "None" + if entry['@class'] in self.settings.sequences['start']: + if entry['cache']: + self.cache = entry['cache']['@id'] + else: + self.cache = "None" + return False + + def result(self, store: ResultStore, name=None) -> None: + results = {"start": self.first, "end": self.last, "duration": self.last - self.first} + for sid in self.sequences: + seq = self.sequences[sid] + #print([end-start for start,end in seq]) + results[f"sequence_{sid}_duration"] = sum([end-start for start,end in seq]) + store.add(Result(type(self), results)) + + +class BiogamesTasks(Analyzer): + __name__ = "BiogamesTasks" + DATA_CLASSES = ("de.findevielfalt.games.game2.instance.log.entry.LogEntryQuestion", ) + BOARD_CLASSES = ("de.findevielfalt.games.game2.instance.log.entry.ShowBoardLogEntry",) + + def __init__(self, settings: LogSettings) -> None: + super().__init__(settings) + self.settings: LogSettings = settings + self.tasks = {} + self.last_board = None + self.instance_config_id: str = None + + def process(self, entry: dict) -> bool: + if self.instance_config_id is None: + if entry[self.settings.type_field] in self.settings.custom['instance_start']: + self.instance_config_id = json_path(entry, self.settings.custom['instance_config_id']) + if self.is_task(entry) and self.last_board: + entry['__duration'] = entry['timestamp'] - self.last_board['timestamp'] + self.tasks[self.ids()] = entry + if self.is_board(entry): + self.last_board = entry + return False + + def result(self, store: ResultStore, name=None) -> None: + results = {} + for ids in self.tasks: + task = self.tasks[ids] + for action in task['selected_actions']: + if self.is_dollar_action(action): + results[ids] = {"duration": task['__duration'], "result": action['increment']} + store.add(Result(type(self), results)) + + def ids(self): + return f"{self.instance_config_id}_{self.last_board['sequence_id']}_{self.last_board['board_id']}" + + def is_task(self, entry) -> bool: + return entry['@class'] in self.DATA_CLASSES + + def is_board(self, entry) -> bool: + return entry['@class'] in self.BOARD_CLASSES + + def is_dollar_action(self, action): + return action['@class'] in ("de.findevielfalt.games.game2.instance.action.IncrementDiversityDollarAction") + class BiogamesStore(Store): __name__ = "BiogamesStore" diff --git a/analysis/analyzers/render/__init__.py b/analysis/analyzers/render/__init__.py index 24c4d2d..329b93c 100644 --- a/analysis/analyzers/render/__init__.py +++ b/analysis/analyzers/render/__init__.py @@ -1,6 +1,10 @@ +import logging from typing import List + +from analysis.analyzers.analyzer import ResultStore from .. import Result +logger = logging.getLogger(__name__) class Render: result_types = [] @@ -8,6 +12,11 @@ class Render: def render(self, results: List[Result], name=None) -> [str]: raise NotImplementedError() + def render_store(self, store: ResultStore, name=None) -> str: + logging.getLogger(__name__).warning("using default implementation!") + for category in store.get_categories(): + self.render(store.get_category(category), name=name) + def filter(self, results: List[Result]): if len(self.result_types) == 0: return results diff --git a/analysis/analyzers/render/biogames.py b/analysis/analyzers/render/biogames.py index 20b2cac..ceb1d8c 100644 --- a/analysis/analyzers/render/biogames.py +++ b/analysis/analyzers/render/biogames.py @@ -1,4 +1,5 @@ import json +import tempfile from collections import defaultdict from typing import List, Tuple @@ -9,8 +10,13 @@ from scipy.interpolate import interp1d import networkx as nx import itertools -from analysis.analyzers import Store, BiogamesStore, SimulationOrderAnalyzer -from analysis.util.meta_temp import CONFIG_NAMES +from analysis.analyzers import Store, BiogamesStore, SimulationOrderAnalyzer, LocationAnalyzer, BiogamesDuration, \ + BiogamesTasks, GameFieldInstanceGroup +from analysis.analyzers.analyzer import ResultStore +from analysis.analyzers.render.default import GeoJSON +from analysis.util.geo import calc_distance, calc_distance_simplified +from analysis.util.meta_temp import CONFIG_NAMES, TASK_NAMES, CACHE_NAMES, SEQUENCE_NAMES +from analysis.util.output import flat_dict_to_csv, pretty_ts from . import Render from .. import Result, SimulationRoundsAnalyzer, BoardDurationAnalyzer, ActivityMapper @@ -201,3 +207,60 @@ class SimulationGroupRender(Render): name=name) result_types = [SimulationOrderAnalyzer] + +class OEBRender(Render): + result_types = [LocationAnalyzer, BiogamesTasks, BiogamesDuration, GameFieldInstanceGroup] + timestamp_fields = ("timestamp", "start", "end") + + def render(self, results: List[Result], name=None) -> [str]: + data = {} + for r in self.filter(results): + if r.analysis() is LocationAnalyzer: + geojson = GeoJSON() + json = geojson.make_geojson(r.get()) + data[f"{r.analysis().__name__}__distance"] = calc_distance(json, "features.0.geometry.coordinates", load=False) + data[f"{r.analysis().__name__}__distance_simplified"] = calc_distance_simplified(json, "features.0.geometry.coordinates", load=False) + else: + for i in r.get(): + a = r.analysis().__name__ + value = r.get()[i] + if i in self.timestamp_fields: + value = pretty_ts(value) + key = f"{a}__{i}" + key = self.replace(key, i) + if type(value) is dict: + for j in value: + data[key+"__"+j] = value[j] + else: + data[key] = value + return data + + def render_store(self, store: ResultStore, name=None) -> str: + data = [] + for category in store.get_categories(): + data.append(self.render(store.get_category(category))) + #import json + #print(json.dumps(data, indent=1)) + csv = flat_dict_to_csv(data) + #print(csv) + if name: + filename = str(name) + ".csv" + else: + filename = "/tmp/biogames" + ".csv" + try: + with open(filename, "w") as out: + out.write(csv) + except PermissionError as e: + raise PermissionError(e, filename) + return filename + + def replace(self, key, i): + if i in TASK_NAMES: + key = f"{TASK_NAMES[i]} ({key})" + if "sequence_" in i: + sid = i.split("_")[1] + cache, seq = sid.split("+") + cache = CACHE_NAMES.get(cache, cache) + seq = SEQUENCE_NAMES.get(seq, seq) + key = f"{cache}->{seq} {sid} duration" + return key \ No newline at end of file diff --git a/analysis/analyzers/render/default.py b/analysis/analyzers/render/default.py index 8ee218f..dfe833d 100644 --- a/analysis/analyzers/render/default.py +++ b/analysis/analyzers/render/default.py @@ -1,3 +1,4 @@ +import copy import json import logging from typing import List @@ -90,22 +91,27 @@ class GeoJSON(SpatialRender, Render): ] } + def make_geojson(self, src): + coordinates = [] + times = [] + for location in src: + #print(location) + coordinates.append(location["location"]["coordinates"]) + times.append(location["timestamp"]) + template = copy.deepcopy(self.template) + template["features"][0]["properties"] = {"times": times} + template["features"][0]["geometry"]["coordinates"] = coordinates + return template + def render(self, results: List[Result], name=None) -> [str]: files = [] for result in self.filter(results): - coordinates = [] - times = [] - for location in result.get(): - #print(location) - coordinates.append(location["location"]["coordinates"]) - times.append(location["timestamp"]) if name: filename = str(name) + ".geojson" else: filename = str(result.name) + ".geojson" + json = self.make_geojson(result.get()) with open(filename, "w") as out: - self.template["features"][0]["properties"] = {"times": times} - self.template["features"][0]["geometry"]["coordinates"] = coordinates json.dump(self.template, out, indent=1) files.append(filename) return files diff --git a/analysis/util/geo.py b/analysis/util/geo.py index 90257d6..cd16582 100644 --- a/analysis/util/geo.py +++ b/analysis/util/geo.py @@ -1,7 +1,7 @@ import json import pyproj -from shapely.geometry import LineString +from shapely.geometry import LineString, mapping from shapely.ops import transform from functools import partial @@ -16,10 +16,18 @@ def distance(track): return transform(project, track).length -def json_to_track(geojson, path): - return LineString(json_path(json.loads(geojson), path)) +def json_to_track(geojson, path, load=True): + if load: + geojson = json.loads(geojson) + return LineString(json_path(geojson, path)) -def calc_distance(geojson: str, path="coordinates"): - track = json_to_track(geojson, path) - return distance(track) \ No newline at end of file +def calc_distance(geojson: str, path="coordinates", load=True): + track = json_to_track(geojson, path, load) + return distance(track) + + +def calc_distance_simplified(geojson, path="coordinates", load=True): + track = json_to_track(geojson, path, load) + simplified = track.simplify(0.0002, preserve_topology=True) + return distance(simplified) \ No newline at end of file diff --git a/analysis/util/meta_temp.py b/analysis/util/meta_temp.py index 5795537..d966a0b 100644 --- a/analysis/util/meta_temp.py +++ b/analysis/util/meta_temp.py @@ -130,4 +130,75 @@ GEOJSON_PATTERN = """{ } """# TODO: fix me -GEOJSON_COORDINATES = "[{lon},{lat}]" \ No newline at end of file +GEOJSON_COORDINATES = "[{lon},{lat}]" + +TASK_NAMES = { + "16fc3117-61db-4f50-b84f-81de6310206f_13127209-103c-4aed-9cce-b8a2cd9f7663_32e93082-1aa7-11e5-9827-74d43509b03a": "Lebensraum", + "16fc3117-61db-4f50-b84f-81de6310206f_13127209-103c-4aed-9cce-b8a2cd9f7663_3a27040f-1a9c-11e5-9827-74d43509b03a": "Simulation", + "16fc3117-61db-4f50-b84f-81de6310206f_2119b80e-74d3-4f3b-b0e0-e6a1f2c1d075_096093b0-d1ca-49f3-8d51-f32fa8874db5": "Biosphärenreservat", + "16fc3117-61db-4f50-b84f-81de6310206f_2119b80e-74d3-4f3b-b0e0-e6a1f2c1d075_b10951a5-1a8a-11e5-b1a2-74d43509b03a": "Simulation", + "16fc3117-61db-4f50-b84f-81de6310206f_41abfe17-aef3-41ee-b1e5-eedc8208680f_255d9c6d-1aa0-11e5-9827-74d43509b03a": "Simulation", + "16fc3117-61db-4f50-b84f-81de6310206f_41abfe17-aef3-41ee-b1e5-eedc8208680f_e0d2dee8-1a9f-11e5-9827-74d43509b03a": "Fellbestimmung", + "16fc3117-61db-4f50-b84f-81de6310206f_b9571a6b-c537-4a92-8618-2d73415dec87_10c3329f-7a88-4aa4-9567-14c811d2a6bc": "Lockstock-Code", + "16fc3117-61db-4f50-b84f-81de6310206f_b9571a6b-c537-4a92-8618-2d73415dec87_5732fe6c-1a9e-11e5-9827-74d43509b03a": "Lockstock-Nachweis", + "16fc3117-61db-4f50-b84f-81de6310206f_b9571a6b-c537-4a92-8618-2d73415dec87_e4bbaf4c-1a9d-11e5-9827-74d43509b03a": "Simulation", + "16fc3117-61db-4f50-b84f-81de6310206f_e08ffe7c-b24d-4fcd-9355-8a459a2c07b7_597c651a-1a8c-11e5-b1a2-74d43509b03a": "Simulation", + "16fc3117-61db-4f50-b84f-81de6310206f_e08ffe7c-b24d-4fcd-9355-8a459a2c07b7_da49b7be-bc13-11e4-a0de-6364e0bfe983": "Holzbedarf", + "17d401a9-de21-49a2-95bc-7dafa53dda64_027dcc39-d642-4900-91c4-abbd9c317cb8_610e91d9-0a1c-4a38-9399-deb0ff8dcb05": "Fellbestimmung", + "17d401a9-de21-49a2-95bc-7dafa53dda64_027dcc39-d642-4900-91c4-abbd9c317cb8_6a03c92d-9e23-4c67-9e76-6a5e28224371": "Simulation", + "17d401a9-de21-49a2-95bc-7dafa53dda64_25a3a482-a119-4db4-8c4e-235ea9d8dab7_90a01be2-dc8a-4733-b302-de5554969453": "Simulation", + "17d401a9-de21-49a2-95bc-7dafa53dda64_25a3a482-a119-4db4-8c4e-235ea9d8dab7_914778bc-f7e9-4327-a78b-71b6fa8762b1": "Biosphärenreservat", + "17d401a9-de21-49a2-95bc-7dafa53dda64_7a8ff4c4-7976-45e0-8ef5-cb386d536cb3_3ae4452e-ed67-4687-849d-e9341fca2900": "Simulation", + "17d401a9-de21-49a2-95bc-7dafa53dda64_7a8ff4c4-7976-45e0-8ef5-cb386d536cb3_f6f5c087-487c-43d8-9409-648a59684a09": "Lebensraum", + "17d401a9-de21-49a2-95bc-7dafa53dda64_97b86d4e-4724-4431-9c94-d2f57696fe2e_26e6558e-8069-45a1-961d-ab1ec9c5aa83": "Holzbedarf", + "17d401a9-de21-49a2-95bc-7dafa53dda64_97b86d4e-4724-4431-9c94-d2f57696fe2e_970ff4e0-16bd-4380-8e69-91a324a59523": "Simulation", + "17d401a9-de21-49a2-95bc-7dafa53dda64_a4f5c5d8-43b0-45f3-b3cf-3749fcb81f05_3366d6a3-684f-423a-bd7f-5c0107d4b972": "Simulation", + "17d401a9-de21-49a2-95bc-7dafa53dda64_a4f5c5d8-43b0-45f3-b3cf-3749fcb81f05_a7188b81-e25b-456d-9742-5f11adb7d461": "Lockstock-Nachweis", + "17d401a9-de21-49a2-95bc-7dafa53dda64_a4f5c5d8-43b0-45f3-b3cf-3749fcb81f05_d29537b9-de0b-42c2-b3da-27a3dbc57988": "Lockstock-Code", +} + +CACHE_NAMES = { + "043ab9fe-64e8-4e76-8bf6-8cc9db35eba1": "1a_Infozentrum", + "37f326ed-9732-44b5-9ba7-e666d31cc4e7": "2a_Holzlager", + "bf96eee0-4c92-43d8-aced-a95e4eedae9f": "2b_Holzstapel", + "a5723715-7ba7-4431-9d0b-c91c351a3ccc": "3a_Lebensraum_Hecke", + "dd68ba57-a081-46be-9a76-e49cd5209383": "3b_Lebensraum_Hecke", + "bb21628e-d039-4c16-9fe1-68de7f448fa4": "4a_Lockstock_finden", + "8291c397-b3a9-4564-9365-bd660ab1abcc": "4b_Lockstock_finden", + "e92d8175-a65f-40de-ae76-3cbde55dfd4d": "5a_Straße", + "30451de3-2d5d-44c7-84b2-2abddbc8adcc": "5b_Straße", + "22fcc44c-64d4-4f84-ad05-8107542a04d2": "6a_Jaegerstand", + "1740e151-cd75-45c0-a06e-d724b9d69729": "6a_Jaegerstand", + "6d97d48a-7ac1-4e3a-b797-c2b4aa681a10": "5a_Straße", + "98e60f51-c4d5-4833-bc3b-2820e1bdd09d": "4b_Lockstock_finden", + "61d6dc12-11b5-4a9c-b0d8-7a38a29d772a": "5b_Straße", + "f4762feb-addb-4e82-b923-78f8c7b6aff9": "2b_Holzstapel", + "25b2cc3b-f8fd-4a21-9350-d175d837f6b6": "3a_Lebensraum_Hecke", + "5ba5046f-c956-4c21-aea5-a0a6055ed7e4": "1a_Infozentrum", + "fb60b94b-3f82-4ba9-98ac-f52105bd26f1": "2a_Holzlager", + "12b9584a-14b4-40c6-aa13-9fb11062e917": "4a_Lockstock_finden", + "19908306-8c70-4861-bec8-49e849e94722": "3b_Lebensraum_Hecke", + "None": "initial", + "only": "", +} + +SEQUENCE_NAMES = { + "89b769f8-2c98-4f55-b741-1dfa022c3286": "1_Videoerklaerung", + "286cab41-6a81-4dfe-9bef-e86923ca8c97": "A_Einleitung", + "2119b80e-74d3-4f3b-b0e0-e6a1f2c1d075": "B", + "25a3a482-a119-4db4-8c4e-235ea9d8dab7": "B", + "97b86d4e-4724-4431-9c94-d2f57696fe2e": "C_mit_Dilemma", + "e08ffe7c-b24d-4fcd-9355-8a459a2c07b7": "C_mit_Dilemma", + "5f644fb4-5cc7-43a2-afb4-191dce80c875": "D_Dilemmasequenz", + "847ab5ff-7c98-4cdc-bc9e-bb619a0a98bb": "D_Dilemmasequenz", + "13127209-103c-4aed-9cce-b8a2cd9f7663": "E", + "7a8ff4c4-7976-45e0-8ef5-cb386d536cb3": "E", + "a4f5c5d8-43b0-45f3-b3cf-3749fcb81f05": "F", + "b9571a6b-c537-4a92-8618-2d73415dec87": "F", + "027dcc39-d642-4900-91c4-abbd9c317cb8": "G", + "41abfe17-aef3-41ee-b1e5-eedc8208680f": "G", + "be59a20a-69ce-471b-8f70-76ce200e32c9": "H_Abschlusserzaehlung", + "d4073563-da42-4ad2-9a9b-20ef29da6309": "H_Abschlusserzaehlung", + "54e03082-1a6b-11e5-aa26-00199963ac6e": "seq_score", + "95d82cd3-5bda-465a-8757-7179cdafe590": "seq_score", +} \ No newline at end of file diff --git a/analysis/util/output.py b/analysis/util/output.py new file mode 100644 index 0000000..1ad705f --- /dev/null +++ b/analysis/util/output.py @@ -0,0 +1,15 @@ +from datetime import datetime as dt + +def flat_dict_to_csv(data): + keys = set() + for i in data: + keys = keys.union(set(i.keys())) + keys = sorted(keys) + out = ",".join(keys) + for i in data: + out += "\n" + ",".join([str(i.get(j, "")) for j in keys]) + return out + +def pretty_ts(timestamp, fmt="%Y-%m-%d %H:%M:%S"): + d = dt.fromtimestamp(int(timestamp)/1000.0) + return d.strftime(fmt) \ No newline at end of file diff --git a/selector/config.py b/selector/config.py index 857f538..7b2dd0c 100644 --- a/selector/config.py +++ b/selector/config.py @@ -155,10 +155,81 @@ KML_geo = """{ ] }""" +OEB = """{ + "logFormat": "zip", + "entryType": "@class", + "spatials": [ + "de.findevielfalt.games.game2.instance.log.entry.LogEntryLocation" + ], + "actions": [ + "...QuestionAnswerEvent", + "...SimuAnswerEvent" + ], + "boards": [ + "de.findevielfalt.games.game2.instance.log.entry.ShowBoardLogEntry" + ], + "analyzers": { + "analysis.analyzers": [ + "BiogamesCategorizer", + "LocationAnalyzer", + "BiogamesDuration", + "BiogamesTasks", + "GameFieldInstanceGroup" + ] + }, + "sequences": { + "start": "de.findevielfalt.games.game2.instance.log.entry.LogEntryCache", + "end": { + "@class": "de.findevielfalt.games.game2.instance.log.entry.LogEntryInstanceAction", + "action.@class": "de.findevielfalt.games.game2.instance.action.CacheEnableAction" + } + }, + "custom": { + "simulation_rounds": [ + "de.findevielfalt.games.game2.instance.log.entry.LogEntryQuestion" + ], + "simu_data": [ + "de.findevielfalt.games.game2.instance.data.sequence.simulation.SimulationBoardData" + ], + "instance_start": "de.findevielfalt.games.game2.instance.log.entry.LogEntryStartInstance", + "instance_id": "instance_id", + "instance_config_id": "config.@id", + "sequences2": { + "id_field": "sequence_id", + "start": { + "@class": "de.findevielfalt.games.game2.instance.log.entry.ShowSequenceLogEntry", + "action": "START" + }, + "end": { + "@class": "de.findevielfalt.games.game2.instance.log.entry.ShowSequenceLogEntry", + "action": "PAUSE" + } + }, + "coordinates": "location.coordinates", + "metadata": { + "timestamp": "timestamp", + "gamefield": "instance_id", + "user": "player_group_name" + } + }, + "source": { + "type": "Biogames", + "username": "ba", + "password": "853451", + "host": "https://biogames.kinf.wiai.uni-bamberg.de" + }, + "render": [ + "OEBRender" + ] +} + + +""" CONFIGS = { "Biogames": { "ActivityMapper": ACTIVITY, - "KML": KML + "KML": KML, + "DauerEntfernungPunkteZeit": OEB, }, "Geogames": { "KML": KML_geo, @@ -167,13 +238,14 @@ CONFIGS = { URLS = { "KML": "/", + "DauerEntfernungPunkteZeit": "/", "ActivityMapper": "#", } HOSTS = { #"Biogames": "http://biogames.potato.kinf.wiai.uni-bamberg.de", #"Biogames": "http://www.biodiv2go.de", - "Biogames": "http://biodiv2govm.kinf.wiai.uni-bamberg.de/", + "Biogames": "http://biogames.kinf.wiai.uni-bamberg.de/", "Geogames": "http://log_data/", } diff --git a/tasks/tasks.py b/tasks/tasks.py index 8dfb346..69b1acc 100644 --- a/tasks/tasks.py +++ b/tasks/tasks.py @@ -10,15 +10,17 @@ import time from celery import Celery from analysis import log_analyzer as la from analysis.analyzers import KMLRender, ActivityMapperRender +from analysis.analyzers.render.biogames import OEBRender from clients.webclients import CLIENTS FLASK_DB = 1 REDIS_HOST = "redis" -DATA_PATH = "/app/data/results/" +DATA_PATH = "/data/results/" RENDERERS = { # TODO "KMLRender": KMLRender, "ActivityMapper": ActivityMapperRender, + "OEBRender": OEBRender } app = Celery('tasks', backend='redis://redis', broker='redis://redis') @@ -55,20 +57,25 @@ def analyze(config, log_ids, **kwargs): settings = la.parse_settings(config) store = la.run_analysis([p.path for p in os.scandir(tmpdir.name)], settings, la.LOADERS) os.mkdir(os.path.join(DATA_PATH, uid)) - for category in store.get_categories(): - data = store.get_category(category) - render = RENDERERS[settings.render[0]]() # TODO - print(category, type(category)) - files = render.render(data, name=category[1]) - log.error(files) - for file in files: - try: - head, tail = os.path.split(file) - target = os.path.join(DATA_PATH, uid, tail) - shutil.move(file, target) - results.append(target) - except FileNotFoundError as e: - log.exception(e) + render = RENDERERS[settings.render[0]]() # TODO + files = [] + if settings.render[0] == "OEBRender": + files.append(render.render_store(store)) + else: + for category in store.get_categories(): + data = store.get_category(category) + print(category, type(category)) + files.append(render.render(data, name=category[1])) + log.error(files) + for file in files: + try: + head, tail = os.path.split(file) + target = os.path.join(DATA_PATH, uid, tail) + log.error(target) + log.error(shutil.move(file, target)) + results.append(target) + except FileNotFoundError as e: + log.exception(e) tmpdir.cleanup() update_status(kwargs['username'], kwargs['name'], ('done', 'FINISHED'), results=results)