Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

internationalzation work : generation of the database and of the html #24

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from
62 changes: 62 additions & 0 deletions internationalization/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
SQL Murder Mystery in French
================================================================================

Authors : Adrien Triquet et Carla Danti, based on Knightlab's educational game : SQL Murder Mystery : https://mystery.knightlab.com/
--------------------------------------------------------------------------------

We are implementing a way to generate the database used in the game in French. It is coded as such as, if someone wants to implement their own translated version, they will have the pre existing structure to rely on.
--------------------------------------------------------------------------------

# data_base
The purpose is to generate a database in another language. For now, it is generating a french database. All the files are to be executed with Pyhton 3, as well as SQL Lite (a library used to implement SQL databases).

## How to create the database
Execute generation-python/__main.py__, the database will be created in data-base. You need to open it with a database manager (advice : open it with SQLiteStudio).
It appeals to each files for each class. There is a mother and a child class for each table.

### main.py explanation
The begining of the code is simply to work with the ORM, as it needs an engine to modify the database. Then, tables are constructed when the classes are called, and added to the database.

## data_base directory description :
- **generation_python** : all the files with the code, each file being an obect class, except for Base.py which is necessary to use the ORM, and main.py which is the file to execute to generate the database. See a simple class like ‘interview’, which is more commented, to understand how it works.

- **model_txt** : all the files needed to gather information for the database, that is to say the file we usein the code to translate some information (car makers we want to feature, car models, cities, ...)

- two png schemas for the databases, **schema_english.png** the official database schema given by Kinghtlab for the game, and **schema_french.png**, the french schema we made our code on.

## Principle of the code
We use the ORM (Object-Relational Mapping) SQLAlchemy for SQLite with Python to build the database.

All python class are linked. They generate the database table they have the name of. The first class is any given file is the parent class, with the table attributes, the relations between the tables, and some functions to fill in the tables.
The second class of the file is the child class, used to generate the french database. Some functions are redefined, as the attribute they build can be sepcific to French language or culture (for example the car plate number conventions are specific to different parts of the world).
In addition, they have the heritages to make them work with the ORM.

### model_txt
All files in this directory are used to fill in the databse.
“cities_list.txt” is a list of the 277 biggest French towns, based on a Wikipedia list.
“makers_list.txt” is a list of the 60 car brands most used in France.
“noise_text.txt” is the text of a novel : “Le mystère de la chambre jaune” by Gaston Leroux. It is provided by the Project Gutenberg and is free to use. We use this text to fill the crime descriptions in the table crime_scene_report.
"firstname_list.txt" is a list of the most commun firstnames in France based on a small part of a government free access database.
"lastname_list.txt" is a list of the most commun lastnames in France based on a small part of a government free access database.
"streetname_list.txt" is a list of name of streets in the city of Saint-Nazaire taken in part from https://sql.sh/2716-base-donnnees-rues-france according to their content policy.

--------------------------------------------------------------------------------

# translation_html
The purpose is to enable anyone without html skills to translate in is language.
We use gettext to generate a new html file with string of characters translated from the « walkthrough.html » file.
You can help translating in your language all the string of characters, they all are in « base.po ».
To generate the html, open « config », install python3 if needed. Then install packages needed and create .po and .mo following the instruction.
Then, in « translation.py », please modify all the « fr » according to your language.
Finally run the file. A « fr.hmtl » file is generated in « translation_html ».
You have to translate sentence after sentence. Unfortunately, some sentences are cut for gettext to work properly.
--------------------------------------------------------------------------------

### Licence :
Our work is under MIT License, based on Knightlab's educational game : SQL Murder Mystery


### Authors :
Carla Danti
Adrien Triquet
Both are Telecom SudParis students under the tutorship of Olivier Berger
9 changes: 9 additions & 0 deletions internationalization/data_base/generation_python/Base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

engine = create_engine('sqlite:///../sql-murder-mystery-french.db')
Session = sessionmaker(bind=engine)

Base = declarative_base()

119 changes: 119 additions & 0 deletions internationalization/data_base/generation_python/CrimeSceneReport.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
from sqlalchemy import Column, Integer, Text
from Base import Base, Session, engine

import random

Base.metadata.create_all(engine)
session = Session()


class CrimeSceneReport(Base):
__abstract__ = True
__tablename__ = 'crime_scene_reports'
#in order not to have an "id" column appearing in the database, we put all those columns as primary_keys
date = Column(Integer, primary_key=True)
type = Column(Text, primary_key=True)
description = Column(Text, primary_key=True)
city = Column(Text, primary_key=True)

def __init__(self, type_of_crime, date, city, description):
self.date = date
self.type = type_of_crime
self.description = description
self.city = city

""" Randomly attributes a date between start_year and end_year
Attributes : start_year, end_year (integers) """
def set_date(self, start_year, end_year):
year = random.randint(start_year, end_year)
month = random.randint(1, 12)

if month in [1, 3, 5, 7, 8, 10, 12]:
day = random.randint(1, 31)
if month == 2:
day = random.randint(1, 29)
else:
day = random.randint(1, 30)

if month < 10:
month = "0" + str(month)
if day < 10:
day = "0" + str(day)
c = str(year) + str(month) + str(day)

self.date = int(c)

""" Randomly attributes a description to the report
Arguments : path_file(char) : relative path leading to the file you want to use to set descriptions, must be in a
readable format
start(int) : number of the line where you want to begin picking up lines for description
end(int) : umber of the line where you want to end picking up the lines """""

def set_description(self, path_file, start, end):
# get the number of lines in the text to drown the clue in noise
file = open(path_file, "r")
n_lines = 0
line = file.readline()
while line:
n_lines += 1
line = file.readline()
file.close()

index = random.randint(start, n_lines - end)

file = open(path_file, "r")
description = file.readline()
count = 0
while count < index:
count += 1
description = file.readline()
file.close()

self.description = description

""" Randomly fills in the type of crime committed
Argument : types(list) : list of the type of crimes you want to put in the database """
def set_type(self, types):
index = random.randint(0, len(types)-1)
type_of_crime = types[index]

self.type = type_of_crime

""" Randomly selects a city on a given file (one city per line, and in a readable format)
Arguments : path_file : relative path to the list of cities """
def set_city(self, path_file):
# get the number of lines in the file
file = open(path_file, "r")
n_cities = 0
line = file.readline()
while line:
n_cities += 1
line = file.readline()
file.close()

index = random.randint(1, n_cities)
file = open(path_file, "r")
city = file.readline()
count = 0
while count < index:
count += 1
city = file.readline()
file.close()

self.city = city


class CrimeSceneReportFrench(CrimeSceneReport):
__tablename__ = 'rapports_scene_de_crime'

def __init__(self):
self.city = Column('ville', Text)

types = ["incendie criminel", "agression", "chantage", "corruption", "fraude", "meurtre", "braquage",
"contrebande", "vol"]

CrimeSceneReport.__init__(self, self.type, self.city, self.description, self.date)
self.set_date(2017, 2019)
self.set_description("../model_txt/noise_text.txt", 77, 369)
self.set_type(types)
self.set_city("../model_txt/cities_list.txt")
133 changes: 133 additions & 0 deletions internationalization/data_base/generation_python/DriversLicense.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
from sqlalchemy import Column, Integer, Text, ForeignKey
from sqlalchemy.orm import relationship
from Base import Base, Session, engine

import random
import string

Base.metadata.create_all(engine)
session = Session()


class DriversLicense(Base):
__abstract__ = True
#__tablename__ = 'drivers_licenses'
id = Column(Integer, primary_key=True)
age = Column('age', Integer)
height = Column('height', Integer)
eye_color = Column('eye_color', Text)
hair_color = Column('hair_color', Text)
gender = Column('gender', Text)
plate_number = Column('plate_number', Text)
car_make = Column('car_make', Text)
car_model = Column('car_model', Text)

def __init__(self, age, height, eye_color, hair_color, gender, plate_number, car_make, car_model):
self.age = age
self.height = height
self.eye_color = eye_color
self.hair_color = hair_color
self.gender = gender
self.plate_number = plate_number
self.car_make = car_make
self.car_model = car_model

""" Randomly fills in the age of the driver
Arguments : age_min, age_max (integers) """
def set_age(self, age_min, age_max):
self.age = random.randint(age_min, age_max)

""" Randomly fills in the height of the driver
Arguments : h_min, h_max (integers) """
def set_height(self, h_min, h_max):
self.height = random.randint(h_min, h_max)

""" Randomly fills in the eye color
Argument : eye_colors(list) """
def set_eye_color(self, eye_colors):
self.eye_color = random.choice(eye_colors)

""" Randomly fills in the hair color
Argument : hair_colors(list) """
def set_hair_color(self, hair_colors):
self.hair_color = random.choice(hair_colors)

""" Randomly fills in the gender of the driver
Argument : genders(list) """
def set_gender(self, genders):
self.gender = random.choice(genders)

""" Randomly fills in the car makers
Argument : car_makers(path_file) : path to the file with the list of car makers you want to feature (one maker
per line, and in a readable format) """
def set_car_make(self, car_makers):
file = open(car_makers, "r")
# get the number of lines in the file
n = 0
line = file.readline()
while line:
n += 1
line = file.readline()
file.close()
# get a random line to pick the car maker
index = random.randint(0, n-1)
file = open(car_makers, "r")
car_maker = file.readline()
count = 0
while count < index:
count += 1
car_maker = file.readline()
self.car_make = car_maker

""" Randomly fills in the car model
Argument : car_models(path_file) : path to the file with the list of car models you want to feature (one model
per line, and in a readable format) """
def set_car_model(self, car_models):
file = open(car_models, "r")
# get the number of lines in the file
n = 0
line = file.readline()
while line:
n += 1
line = file.readline()
file.close()
# get a random line to pick the car model
index = random.randint(0, n-1)
file = open(car_models, "r")
car_model = file.readline()
count = 0
while count < index:
count += 1
car_model = file.readline()
self.car_model = car_model


class DriversLicenseFrench(DriversLicense):
__tablename__ = 'permis_de_conduire'

def set_plate_number(self):
# making of plaque_number following French standards
l1 = random.choice(string.ascii_uppercase)
l2 = random.choice(string.ascii_uppercase)
m = random.randint(100, 999)
l3 = random.choice(string.ascii_uppercase)
l4 = random.choice(string.ascii_uppercase)

self.plate_number = l1 + l2 + "-" + str(m) + "-" + l3 + l4

def __init__(self):
eye_colors = ["noisette", "noir", "bleu", "marron", "vert"]
hair_colors = ["noir", "blond", "chatain", "gris", "blanc", "roux"]
genders = ["féminin", "masculin"]

DriversLicense.__init__(self, self.age, self.height, self.eye_color, self.hair_color, self.gender,
self.plate_number, self.car_make, self.car_model)
self.set_age(18, 90)
self.set_height(150, 200)
self.set_eye_color(eye_colors)
self.set_hair_color(hair_colors)
self.set_gender(genders)
self.set_plate_number()
self.set_car_make("../model_txt/makers_list.txt")
self.set_car_model("../model_txt/models_list.txt")

Loading