Source code for alter_ego.exports.otree

import os
from typing import Any, Dict, List, Optional, Union
from alter_ego.structure import Thread, Conversation
from alter_ego.utils import to_html

# Constants for key formats
PLAYER_KEY_FORMAT = "__alter_ego/player/{}/{}"
GROUP_KEY_FORMAT = "__alter_ego/group/{}/{}"
ROUND_KEY_FORMAT = "__alter_ego/round/{}/{}"
PARTICIPANT_KEY_FORMAT = "__alter_ego/participant"
SESSION_KEY_FORMAT = "__alter_ego/session"

OUTPATH = ".ego_output/"
NO_SAVE = False
FULL_SAVE = True


[docs] def html_history(thread: Thread) -> None: """Convert thread history to HTML format.""" thread.html_history = [ {role: to_html(message) for role, message in record.items()} for record in thread._history ]
[docs] def save(thread: Thread) -> None: """Save the thread data.""" if not NO_SAVE: outdir = OUTPATH + thread.metadata["otree_session"] # save json backup thread.save(outdir=outdir, full_save=False) if FULL_SAVE: # also save pickle thread.save(outdir=outdir, full_save=True)
[docs] def add_hooks(thread: Thread) -> None: """Add history hooks to a thread.""" thread.history_hooks.add(html_history) thread.history_hooks.add(save)
[docs] class Assigner: """ A class for attribute assignment operations. """ def __init__( self, assignees: List[Any], key: str, metadata: Optional[Dict[str, Any]] = None ) -> None: """ Initialize an instance of Assigner. :param assignees: A list of objects to be assigned. :param key: The key used for assigning. """ self.assignees = assignees self.key = key self.metadata = metadata if metadata is not None else dict() def __bool__(self) -> bool: """Check if the key exists in the first assignee's vars dict.""" return self.key in self.assignees[0].vars def __enter__(self) -> Any: self.value = self.assignees[0].vars[self.key] return self.value def __exit__(self, *args: Any) -> bool: self.set(self.value) return False
[docs] def set(self, value: Union[Thread, Conversation]) -> None: """Assign value to the 'vars' dictionary of all assignees.""" if isinstance(value, Conversation): for thread in value: thread.metadata |= self.metadata add_hooks(thread) elif isinstance(value, Thread): value.metadata |= self.metadata add_hooks(value) else: raise NotImplementedError( "Only a Thread or a Conversation can be assigned." ) for assignee in self.assignees: assignee.vars[self.key] = value
[docs] def unset(self) -> None: """Unset the key in all assignees.""" for assignee in self.assignees: if self.key in assignee.vars: del assignee.vars[self.key]