diff --git a/.quarto/project-cache/deno-kv-file b/.quarto/project-cache/deno-kv-file new file mode 100644 index 0000000..f31f490 Binary files /dev/null and b/.quarto/project-cache/deno-kv-file differ diff --git a/_quarto.yml b/_quarto.yml new file mode 100644 index 0000000..395bb3c --- /dev/null +++ b/_quarto.yml @@ -0,0 +1,11 @@ +project: + type: website + +execute: + engine: jupyter + +jupyter: + python: ".venv/bin/python" + +environment: + PYTHONPATH: "/home/cantabile/Documents/repos/button" \ No newline at end of file diff --git a/button_2/blackboard.py b/button_2/blackboard.py deleted file mode 100644 index 24f8d1b..0000000 --- a/button_2/blackboard.py +++ /dev/null @@ -1,50 +0,0 @@ -import marimo - -__generated_with = "0.16.2" -app = marimo.App(width="medium") - - -@app.cell -def _(): - import marimo as mo - return (mo,) - - -@app.cell -def _(mo): - mo.md(r"""## employee text generator""") - return - - -@app.cell -def _(): - from classes.entities.employee import Employee - return (Employee,) - - -@app.cell -def _(Employee): - employee = Employee() - return (employee,) - - -@app.cell -def _(employee): - employee.employee_id - return - - -@app.cell -def _(employee): - employee.job_title - return - - -@app.cell -def _(employee): - employee.department - return - - -if __name__ == "__main__": - app.run() diff --git a/button_2/blackboard.qmd b/button_2/blackboard.qmd new file mode 100644 index 0000000..b45d537 --- /dev/null +++ b/button_2/blackboard.qmd @@ -0,0 +1,78 @@ +--- +execute: + jupyter: + python: ".venv/bin/python" +--- + +```{python } + +from classes.data.button_dat import ButtonDat + + +``` + + + + +```{python} +button_dat = ButtonDat() + +``` + +Button dat should have an attribute that is edges. + +```{python} +button_dat.edges_df + + +``` + +Button dat should has have nodes df. + +```{python} +button_dat.nodes_df + +``` + +## employee + +Now to try employee, which takes button dat as input. + +```{python} +from classes.entities.employee import Employee + +``` + + +```{python} +employee = Employee(button_dat) + +``` + +## text rendering + +```{python} + +from classes.text_gen.textgen_employee import EmployeeTextGenerator + +# generate the text +employee_text = EmployeeTextGenerator(employee) + +vars(employee_text) + +``` + +```{python} +from classes.text_render.text_render_employee import EmployeeTextRenderer + +employee_text_rendered = EmployeeTextRenderer(employee_text) + +``` + +This is where I apply wrappers. + +```{python} + +employee_text_rendered.rendered_text + +``` diff --git a/button_2/blackboard_node_logic.py b/button_2/blackboard_node_logic.py new file mode 100644 index 0000000..bcdf419 --- /dev/null +++ b/button_2/blackboard_node_logic.py @@ -0,0 +1,27 @@ +# this script is for sketching the node engine logic + + +# this would be done in the game engine + +from classes.game.node_context import NodeContext +from classes.entities.employee import Employee +from classes.data.button_dat import ButtonDat + +button_dat = ButtonDat() + +# aha so I can refactor this to be generated by the context? +employee = Employee(button_dat.employee_df.iloc[0]['job_title'], + button_dat.employee_df.iloc[0]['department']) + +context = NodeContext(employee=employee) + + +# node engine logic +from classes.text_gen.textgen_employee import EmployeeTextGenerator + +# todo node title + +employee.set_current_titles() + +employee_text_gen = EmployeeTextGenerator() +print(employee_text_gen.generate_text(context)) diff --git a/button_2/classes/data/button_dat.py b/button_2/classes/data/button_dat.py index 6312996..a6d6e10 100644 --- a/button_2/classes/data/button_dat.py +++ b/button_2/classes/data/button_dat.py @@ -1,8 +1,15 @@ import pandas as pd +import os +from pathlib import Path class ButtonDat: def __init__(self): - self.edges_df = pd.read_csv('button_2/data/edges.csv') - self.nodes_df = pd.read_csv('button_2/data/nodes.csv') - self.text_df = pd.read_csv('button_2/data/text.csv') - self.employee_df = pd.read_csv('button_2/data/employee.csv') + # Get the directory where this file is located + current_dir = Path(__file__).parent + # Navigate to the data directory + data_dir = current_dir.parent.parent / 'data' + + self.edges_df = pd.read_csv(data_dir / 'edges.csv') + self.nodes_df = pd.read_csv(data_dir / 'nodes.csv') + self.text_df = pd.read_csv(data_dir / 'text.csv') + self.employee_df = pd.read_csv(data_dir / 'employee.csv') \ No newline at end of file diff --git a/button_2/classes/textblock/__init__.py b/button_2/classes/entities/__init__.py similarity index 100% rename from button_2/classes/textblock/__init__.py rename to button_2/classes/entities/__init__.py diff --git a/button_2/classes/entities/employee.py b/button_2/classes/entities/employee.py index a34abef..e58bfe2 100644 --- a/button_2/classes/entities/employee.py +++ b/button_2/classes/entities/employee.py @@ -1,8 +1,18 @@ +import random +from classes.data.button_dat import ButtonDat + class Employee: - def __init__(self): - self.employee_id = "#eiLaSi-LV-426-ekaCehT" - self.job_title = None - self.department = None + def __init__(self, button_dat: ButtonDat): + self.employee_id = "#eilaslv426ekaceht", + self.job_title = button_dat.employee_df.job_title[0] + self.department = button_dat.employee_df.department[0] + self.button_dat = button_dat def reorg(self): - pass \ No newline at end of file + self.job_title = random.choice(self.button_dat.employee_df.job_title) + self.department = random.choice(self.button_dat.employee_df.department) + + def set_current_titles(self): + reorg_now = random.choices([True, False], weights=[0.1, 0.9])[0] + if reorg_now: + self.reorg() \ No newline at end of file diff --git a/button_2/tests/textblock/__init__.py b/button_2/classes/game/__init__.py similarity index 100% rename from button_2/tests/textblock/__init__.py rename to button_2/classes/game/__init__.py diff --git a/button_2/classes/game/node_context.py b/button_2/classes/game/node_context.py new file mode 100644 index 0000000..f6b1ba1 --- /dev/null +++ b/button_2/classes/game/node_context.py @@ -0,0 +1,18 @@ +from ..entities.employee import Employee + +class NodeContext: + def __init__( + self, + employee: Employee#, + # node_name: str, + # game_path: str, + # button_dat: str, + # choices: list = None, + # text_type: str = None + ): + self.employee = employee + # self.node_name = node_name + # self.game_path = game_path + # self.button_dat = button_dat + # self.choices = choices or [] + # self.text_type = text_type \ No newline at end of file diff --git a/button_2/classes/text_gen/__init__.py b/button_2/classes/text_gen/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/button_2/classes/text_gen/textgen_employee.py b/button_2/classes/text_gen/textgen_employee.py new file mode 100644 index 0000000..cf5309c --- /dev/null +++ b/button_2/classes/text_gen/textgen_employee.py @@ -0,0 +1,13 @@ +from ..entities.employee import Employee + +class EmployeeTextGenerator(): + + def __init__(self, employee: Employee): + employee.set_current_titles() + + self.job_title = employee.job_title + self.department = employee.department + self.employee_text = self.generate_employee_text() + + def generate_employee_text(self) -> str: + return f"Your day begins as a {self.job_title} in the {self.department} department." diff --git a/button_2/classes/text_render/__init__.py b/button_2/classes/text_render/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/button_2/classes/text_render/text_render_employee.py b/button_2/classes/text_render/text_render_employee.py new file mode 100644 index 0000000..315012c --- /dev/null +++ b/button_2/classes/text_render/text_render_employee.py @@ -0,0 +1,10 @@ +from ..text_gen.textgen_employee import EmployeeTextGenerator + +class EmployeeTextRenderer: + def __init__(self, employee_text_gen: EmployeeTextGenerator): + self.employee_text_gen = employee_text_gen + self.rendered_text = self.render_text() + + def render_text(self) -> str: + # We need to apply string wrapping in renderers. + return self.employee_text_gen.employee_text diff --git a/button_2/data/employee.csv b/button_2/data/employee.csv index d9f3934..31dafca 100644 --- a/button_2/data/employee.csv +++ b/button_2/data/employee.csv @@ -1,6 +1,16 @@ job_title,department -data scientist,data -data analyst,data analytics -data engineer,business intelligence -analytics engineer,data & analytics -business intelligence analyst,data science +Data scientist,Data & analytics +Data analyst,Data analytics +Data engineer,Businsess intelligence +Analytics engineer,Data & AI +Business intelligence analyst,Data science +ML engineer,AI +AI engineer,AI/ML +Decision scientist,Machine learning +Insights analyst,Data strategy +Data architect,Data governance & strategy +Predictive modeller,Data enablement +Research software engineer,Data innovation +ML developer,Data transformation +AI developer,Analytics +Data developer,Insights & reporting diff --git a/button_2/tests/entities/test_employee.py b/button_2/tests/entities/test_employee.py index 88c9edb..94f268f 100644 --- a/button_2/tests/entities/test_employee.py +++ b/button_2/tests/entities/test_employee.py @@ -1,22 +1,25 @@ from button_2.classes.entities.employee import Employee import pandas as pd -from button_2.classes.button_dat import ButtonDat +from button_2.classes.data.button_dat import ButtonDat + +button_dat = ButtonDat() +employee = Employee( + job_title=button_dat.employee_df.iloc[0]['job_title'] if not button_dat.employee_df.empty else None, + department=button_dat.employee_df.iloc[0]['department'] if not button_dat.employee_df.empty else None +) def test_employee_init(): - employee = Employee() assert employee is not None assert hasattr(employee, 'employee_id') assert hasattr(employee, 'job_title') assert hasattr(employee, 'department') def test_employee_methods(): - employee = Employee() assert callable(employee.reorg), ( "Employee should have a callable reorg method" ) def test_texgen_employee_attributes(): - employee = Employee() assert employee.employee_id is not None assert employee.job_title is not None assert employee.department is not None @@ -30,9 +33,11 @@ def helper_test_reorg_method(): # low probability of change expected, # so will run multiple times in main test - employee = Employee() initial_state = (employee.job_title, employee.department) - employee.reorg() + employee.set_current_titles( + job_titles=button_dat.employee_df['job_title'].dropna().values, + departments=button_dat.employee_df['department'].dropna().values + ) new_state = (employee.job_title, employee.department) return {"state_change": initial_state != new_state, "job_title": employee.job_title, @@ -52,7 +57,6 @@ def test_employee_reorg_method_changes_state(): changes = sum(sim_df['state_change']) - button_dat = ButtonDat() assert changes > 0, ( "reorg method should change employee state occasionally" @@ -62,11 +66,11 @@ def test_employee_reorg_method_changes_state(): ) # check generated job titles are expected values from employee df assert set(sim_df["job_title"].unique()).issubset( - set(button_dat.employee["job_title"].unique()) + set(button_dat.employee_df["job_title"].unique()) ), "Unexpected job titles generated" # check generated departments are expected values from employee df assert set(sim_df["department"].unique()).issubset( - set(button_dat.employee["department"].unique()) + set(button_dat.employee_df["department"].unique()) ), "Unexpected departments generated" diff --git a/button_2/tests/textgen/__init__.py b/button_2/tests/textgen/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/button_2/tests/textgen/test_textgen_employee.py b/button_2/tests/textgen/test_textgen_employee.py new file mode 100644 index 0000000..de5b64a --- /dev/null +++ b/button_2/tests/textgen/test_textgen_employee.py @@ -0,0 +1,21 @@ +from button_2.classes.text_gen.textgen_employee import EmployeeTextGenerator +from button_2.classes.entities.employee import Employee +from button_2.classes.data.button_dat import ButtonDat + +button_dat = ButtonDat() +employee = Employee(button_dat) + +# assert that the text generator works +def test_employee_text_generator(): + + text_generator = EmployeeTextGenerator(employee) + assert text_generator is not None + +# assert that the text generator has attributes: +# job_title +# department + +def test_employee_text_generator_attributes(): + text_generator = EmployeeTextGenerator(employee) + assert hasattr(text_generator, "job_title") + assert hasattr(text_generator, "department") \ No newline at end of file diff --git a/button_2/tests/textrend/__init__.py b/button_2/tests/textrend/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/button_2/tests/textrend/test_textrend_employee.py b/button_2/tests/textrend/test_textrend_employee.py new file mode 100644 index 0000000..f066d0a --- /dev/null +++ b/button_2/tests/textrend/test_textrend_employee.py @@ -0,0 +1,28 @@ +from button_2.classes.entities.employee import Employee +from button_2.classes.data.button_dat import ButtonDat +from button_2.classes.text_gen.textgen_employee import EmployeeTextGenerator +from button_2.classes.text_render.text_render_employee import EmployeeTextRenderer + +button_dat = ButtonDat() +employee = Employee(button_dat) +employee_text = EmployeeTextGenerator(employee) + +def test_employee_text_renderer(): + employee_text_renderer = EmployeeTextRenderer(employee_text) + + # More comprehensive assertions + assert employee_text_renderer.rendered_text is not None + assert isinstance(employee_text_renderer.rendered_text, str) + assert len(employee_text_renderer.rendered_text) > 0 + +def test_employee_text_renderer_type(): + employee_text_renderer = EmployeeTextRenderer(employee_text) + assert hasattr(employee_text_renderer, 'rendered_text') + +def test_employee_text_renderer_consistency(): + employee_text_renderer = EmployeeTextRenderer(employee_text) + + # Should return same result on multiple calls + first_render = employee_text_renderer.rendered_text + second_render = employee_text_renderer.rendered_text + assert first_render == second_render \ No newline at end of file