|
|
|
|
|
|
|
|
|
|
|
import argparse, re |
|
|
|
|
|
from string import Template |
|
|
|
|
|
from typing import NamedTuple |
|
|
|
|
|
|
|
|
|
|
|
from jinja2 import Environment, PackageLoader, select_autoescape |
|
|
|
|
|
|
|
|
|
|
|
# global variables |
|
|
|
|
|
|
|
|
|
|
|
env = Environment( |
|
|
|
|
|
loader=PackageLoader("swjg"), |
|
|
|
|
|
autoescape=select_autoescape |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
parser = argparse.ArgumentParser() |
|
|
|
|
|
|
|
|
|
|
|
# helper functions |
|
|
|
|
|
|
|
|
|
|
|
def get_identifiers_from_template(template): |
|
|
|
|
|
# Template.get_identifiers() doesn't appear until Python 3.11 |
|
|
|
|
|
|
|
|
|
|
|
# Don't substitute anything; get the raw string |
|
|
|
|
|
template_str = Template.safe_substitute() |
|
|
|
|
|
matches = re.findall("\$[a-z0-9_\.]+", template_str) |
|
|
|
|
|
matches = [x[1:] for x in matches] |
|
|
|
|
|
return matches |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# classes and such |
|
|
|
|
|
|
|
|
|
|
|
class Destination(NamedTuple): |
|
|
|
|
|
world: str |
|
|
|
|
|
system: str|None |
|
|
|
|
|
sector: str|None |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Mission: |
|
|
|
|
|
output_destination_template = Template("to $world in the $system system") |
|
|
|
|
|
output_sector_template = Template(", part of the $sector,") |
|
|
|
|
|
value_template = Template("for $value credits") |
|
|
|
|
|
error_template = Template("You haven't given this mission some of the values it needs. Please check: $potential_values") |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, destination:Destination, value:int, *args, **kwargs): |
|
|
|
|
|
# destination: Destination (see above) |
|
|
|
|
|
self.world = destination.world if destination.world is not None else None |
|
|
|
|
|
self.system = destination.system if destination.system is not None else destination.world |
|
|
|
|
|
self.sector = destination.sector if destination.sector is not None else None |
|
|
|
|
|
self.value = value |
|
|
|
|
|
# for arg, val in kwargs.items(): |
|
|
|
|
|
# setattr(self, arg, val) |
|
|
|
|
|
|
|
|
|
|
|
def assemble_templates(self) -> list: |
|
|
|
|
|
# Override this in children |
|
|
|
|
|
template_list = [] |
|
|
|
|
|
if self.world != None: |
|
|
|
|
|
template_list.append(self.output_destination_template) |
|
|
|
|
|
if self.sector != None: |
|
|
|
|
|
template_list.append(self.output_sector_template) |
|
|
|
|
|
template_list.append(self.value_template) |
|
|
|
|
|
return template_list |
|
|
|
|
|
|
|
|
|
|
|
def get_current_values(self) -> dict: |
|
|
|
|
|
return { |
|
|
|
|
|
"world": self.world, |
|
|
|
|
|
"system": self.system, |
|
|
|
|
|
"sector": self.sector, |
|
|
|
|
|
"value": self.value |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
def missing_values(self) -> list: |
|
|
|
|
|
object_vars = vars(self) |
|
|
|
|
|
missing = [] |
|
|
|
|
|
for key, val in object_vars.items(): |
|
|
|
|
|
if val == None: |
|
|
|
|
|
missing.append(key) |
|
|
|
|
|
return missing |
|
|
|
|
|
|
|
|
|
|
|
def assemble_text(self) -> str: |
|
|
|
|
|
missing_vals = self.missing_values() |
|
|
|
|
|
templates = self.assemble_templates() |
|
|
|
|
|
if len(templates) == 0 or len(missing_vals) != 0: # either both of these should be true or neither should |
|
|
|
|
|
raise ValueError(self.error_template.substitute(potential_values=missing_vals)) |
|
|
|
|
|
|
|
|
|
|
|
current_values = self.get_current_values() |
|
|
|
|
|
|
|
|
|
|
|
output = [] |
|
|
|
|
|
for template in templates: |
|
|
|
|
|
output.append(template.substitute(**current_values)) |
|
|
|
|
|
out_text = " ".join(output) |
|
|
|
|
|
out_text = out_text.replace(" ,", ",") |
|
|
|
|
|
out_text += "." |
|
|
|
|
|
return out_text |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class PassengerMission(Mission): |
|
|
|
|
|
output_initial_template = Template("Bring $number passengers") |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, number:int, *args, **kwargs): |
|
|
|
|
|
super(PassengerMission, self).__init__(*args, **kwargs) |
|
|
|
|
|
self.number = number |
|
|
|
|
|
|
|
|
|
|
|
def get_current_values(self) -> dict: |
|
|
|
|
|
base_dict = super(PassengerMission, self).get_current_values() |
|
|
|
|
|
new_dict = { |
|
|
|
|
|
"number": self.number |
|
|
|
|
|
} |
|
|
|
|
|
base_dict.update(new_dict) |
|
|
|
|
|
return base_dict |
|
|
|
|
|
|
|
|
|
|
|
def assemble_templates(self): |
|
|
|
|
|
template_list = [self.output_initial_template] |
|
|
|
|
|
template_list.extend(super(PassengerMission, self).assemble_templates()) |
|
|
|
|
|
return template_list |
|
|
|
|
|
|
|
|
|
|
|
def assemble_text(self) -> str: |
|
|
|
|
|
return super(PassengerMission, self).assemble_text() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CargoMission(Mission): |
|
|
|
|
|
output_initial_template = Template("Deliver $tons tons of $item") |
|
|
|
|
|
output_time_timeplate = Template("in the next $time days") |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, tons:int, item:str, time:int, *args, **kwargs): |
|
|
|
|
|
# tons: integer |
|
|
|
|
|
# item: string (this will not be pluralized in the text) |
|
|
|
|
|
# time: integer (number of days the crew have to complete delivery) |
|
|
|
|
|
# value: integer (value in credits) |
|
|
|
|
|
super(CargoMission, self).__init__(*args, **kwargs) |
|
|
|
|
|
self.tons = tons |
|
|
|
|
|
self.item = item |
|
|
|
|
|
self.time = time |
|
|
|
|
|
|
|
|
|
|
|
def get_current_values(self) -> dict: |
|
|
|
|
|
base_dict = super(CargoMission, self).get_current_values() |
|
|
|
|
|
new_dict = { |
|
|
|
|
|
"tons": self.tons, |
|
|
|
|
|
"item": self.item, |
|
|
|
|
|
"time": self.time |
|
|
|
|
|
} |
|
|
|
|
|
base_dict.update(new_dict) |
|
|
|
|
|
return base_dict |
|
|
|
|
|
|
|
|
|
|
|
def assemble_templates(self): |
|
|
|
|
|
template_list = [self.output_initial_template] |
|
|
|
|
|
if self.time is not None: |
|
|
|
|
|
template_list.append(self.output_time_timeplate) |
|
|
|
|
|
template_list.extend(super(CargoMission, self).assemble_templates()) |
|
|
|
|
|
return template_list |
|
|
|
|
|
|
|
|
|
|
|
def assemble_text(self) -> str: |
|
|
|
|
|
return super(CargoMission, self).assemble_text() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class GroupMission(Mission): |
|
|
|
|
|
output_initial_template = Template("Bring $number members of a $group") |
|
|
|
|
|
|
|
|
|
|
|
def __init__(self, number:int, group:str, *args, **kwargs): |
|
|
|
|
|
super(GroupMission, self).__init__(*args, **kwargs) |
|
|
|
|
|
self.number = number |
|
|
|
|
|
self.group = group |
|
|
|
|
|
|
|
|
|
|
|
def get_current_values(self) -> dict: |
|
|
|
|
|
base_dict = super(GroupMission, self).get_current_values() |
|
|
|
|
|
new_dict = { |
|
|
|
|
|
"number": self.number, |
|
|
|
|
|
"group": self.group |
|
|
|
|
|
} |
|
|
|
|
|
base_dict.update(new_dict) |
|
|
|
|
|
return base_dict |
|
|
|
|
|
|
|
|
|
|
|
def assemble_templates(self): |
|
|
|
|
|
template_list = [self.output_initial_template] |
|
|
|
|
|
template_list.extend(super(GroupMission, self).assemble_templates()) |
|
|
|
|
|
return template_list |
|
|
|
|
|
|
|
|
|
|
|
def assemble_text(self) -> str: |
|
|
|
|
|
return super(GroupMission, self).assemble_text() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# the function that does the thing |
|
|
|
|
|
|
|
|
|
|
|
def main(): |
|
|
|
|
|
import random |
|
|
|
|
|
mission_types = [PassengerMission, CargoMission, GroupMission] |
|
|
|
|
|
missions = [] |
|
|
|
|
|
for _ in range(5): |
|
|
|
|
|
current_mission = random.choice(mission_types) |
|
|
|
|
|
destination = Destination("Alderaan", None, "Core Worlds") |
|
|
|
|
|
number = random.randint(1,8) |
|
|
|
|
|
tons = random.randint(4, 12) |
|
|
|
|
|
item = random.choice(["gravel", "computer chips", "spice", "live ysalamiri", "empty shipping containers"]) |
|
|
|
|
|
time = random.randint(7, 31) |
|
|
|
|
|
value = random.randint(20, 120) * 1000 |
|
|
|
|
|
group = None |
|
|
|
|
|
if current_mission == GroupMission: |
|
|
|
|
|
group = random.choice(["family", "performing troupe", "acrobatic troupe"]) |
|
|
|
|
|
missions.append(current_mission(destination=destination, number=number, tons=tons, item=item, time=time, value=value, group=group)) |
|
|
|
|
|
for mission in missions: |
|
|
|
|
|
# print(mission, mission.__dict__) |
|
|
|
|
|
print(mission.assemble_text()) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Don't do anything if the module is loaded wholesale into something else |
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__": |
|
|
|
|
|
main() |