#!/usr/bin/python
# -*- coding: utf-8 -*-

STARTING_AGE = 18

STARTING_SKILLS = 3

COMMISSION = 8

FIELDS = ("T", "Career", "Spec", "Q", "S", "A",
          "Edu", "BT", "SR", "Rnk", "EM", "Age", "Ben")

TERM = {f: None for f in FIELDS}

CAREERS = {
    'Agent': {
        'Corporate': {'Surv': ('Int', 5), 'Qual': ('Int', 6), 'Adv': ('Int', 7)},
        'Law Enforcement': {'Surv': ('End', 6), 'Qual': ('Int', 6), 'Adv': ('Int', 6)},
        'Intelligence': {'Surv': ('Int', 7), 'Qual': ('Int', 6), 'Adv': ('Int', 5)}},
    'Merchant': {
        'Free Trader': {'Surv': ('Dex', 6), 'Qual': ('Int', 4), 'Adv': ('Int', 6)},
        'Merchant Marine': {'Surv': ('Edu', 5), 'Qual': ('Int', 4), 'Adv': ('Int', 7)},
        'Broker': {'Surv': ('Edu', 5), 'Qual': ('Int', 4), 'Adv': ('Int', 7)}},
    'Scholar': {
        'Physician': {'Surv': ('Edu', 4), 'Qual': ('Int', 6), 'Adv': ('Edu', 8)},
        'Scientist': {'Surv': ('Edu', 4), 'Qual': ('Int', 6), 'Adv': ('Int', 8)},
        'Field Researcher': {'Surv': ('End', 6), 'Qual': ('Int', 6), 'Adv': ('Int', 6)}},
    'Army': {
        'Cavalry': {'Surv': ('Dex', 7), 'Qual': ('End', 5), 'Adv': ('Int', 5)},
        'Support': {'Surv': ('End', 5), 'Qual': ('End', 5), 'Adv': ('Edu', 7)},
        'Infantry': {'Surv': ('Str', 6), 'Qual': ('End', 5), 'Adv': ('Edu', 6)}},
    'Navy': {
        'Line/Crew': {'Surv': ('Int', 5), 'Qual': ('Int', 6), 'Adv': ('Edu', 7)},
        'Flight': {'Surv': ('Dex', 7), 'Qual': ('Int', 6), 'Adv': ('Edu', 5)},
        'Engineering/Gunnery': {'Surv': ('Int', 6), 'Qual': ('Int', 6), 'Adv': ('Edu', 6)}},
    'Marines': {
        'Star Marines': {'Surv': ('End', 6), 'Qual': ('End', 6), 'Adv': ('Edu', 6)},
        'Support': {'Surv': ('End', 5), 'Qual': ('End', 6), 'Adv': ('Edu', 7)},
        'Ground Assault': {'Surv': ('End', 7), 'Qual': ('End', 6), 'Adv': ('Edu', 5)}},
    'Army Officer': {
        'Cavalry': {'Surv': ('Dex', 7), 'Qual': ('End', 5), 'Adv': ('Int', 5)},
        'Support': {'Surv': ('End', 5), 'Qual': ('End', 5), 'Adv': ('Edu', 7)},
        'Infantry': {'Surv': ('Str', 6), 'Qual': ('End', 5), 'Adv': ('Edu', 6)}},
    'Navy Officer': {
        'Line/Crew': {'Surv': ('Int', 5), 'Qual': ('Int', 6), 'Adv': ('Edu', 7)},
        'Flight': {'Surv': ('Dex', 7), 'Qual': ('Int', 6), 'Adv': ('Edu', 5)},
        'Engineering/Gunnery': {'Surv': ('Int', 6), 'Qual': ('Int', 6), 'Adv': ('Edu', 6)}},
    'Marines Officer': {
        'Star Marines': {'Surv': ('End', 6), 'Qual': ('End', 6), 'Adv': ('Edu', 6)},
        'Support': {'Surv': ('End', 5), 'Qual': ('End', 6), 'Adv': ('Edu', 7)},
        'Ground Assault': {'Surv': ('End', 7), 'Qual': ('End', 6), 'Adv': ('Edu', 5)}},
    'Scout': {
        'Exploration': {'Surv': ('End', 7), 'Qual': ('Int', 5), 'Adv': ('Edu', 7)},
        'Survey': {'Surv': ('End', 6), 'Qual': ('Int', 5), 'Adv': ('Int', 8)},
        'Courier': {'Surv': ('End', 5), 'Qual': ('Int', 5), 'Adv': ('Edu', 9)}},
    'Drifter': {
        'Scavenger': {'Surv': ('Dex', 7), 'Qual': ('End', None), 'Adv': ('End', 7)},
        'Wanderer': {'Surv': ('End', 7), 'Qual': ('End', None), 'Adv': ('Int', 7)},
        'Barbarian': {'Surv': ('End', 7), 'Qual': ('End', None), 'Adv': ('Str', 7)}},
    'Entertainer': {
        'Performer': {'Surv': ('Int', 5), 'Qual': ('Int', 5), 'Adv': ('Dex', 7)},
        'Journalist': {'Surv': ('Edu', 7), 'Qual': ('Int', 5), 'Adv': ('Int', 5)},
        'Artist': {'Surv': ('Soc', 6), 'Qual': ('Int', 5), 'Adv': ('Int', 6)}},
    'Rogue': {
        'Enforcer': {'Surv': ('End', 6), 'Qual': ('Dex', 6), 'Adv': ('Str', 6)},
        'Thief': {'Surv': ('Int', 6), 'Qual': ('Dex', 6), 'Adv': ('Dex', 6)},
        'Pirate': {'Surv': ('Dex', 6), 'Qual': ('Dex', 6), 'Adv': ('Int', 6)}},
    'Citizen': {
        'Worker': {'Surv': ('End', 4), 'Qual': ('Edu', 5), 'Adv': ('Edu', 8)},
        'Colonist': {'Surv': ('Int', 7), 'Qual': ('Edu', 5), 'Adv': ('End', 5)},
        'Corporate': {'Surv': ('Soc', 5), 'Qual': ('Edu', 5), 'Adv': ('Int', 6)}},
    'Nobility': {
        'Administrator': {'Surv': ('Int', 4), 'Qual': ('Soc', 10), 'Adv': ('Edu', 6)},
        'Diplomat': {'Surv': ('Int', 5), 'Qual': ('Soc', 10), 'Adv': ('Soc', 7)},
        'Dilettante': {'Surv': ('Soc', 3), 'Qual': ('Soc', 10), 'Adv': ('Int', 8)}},
    }

PSION = {
    'Psion': {
        'Wild Talent': {'Surv': ('Soc', 6), 'Qual': ('Psi', 6), 'Adv': ('Int', 8)},
        'Adept': {'Surv': ('Edu', 4), 'Qual': ('Psi', 6), 'Adv': ('Edu', 8)},
        'Psi-Warrior': {'Surv': ('Edu', 6), 'Qual': ('Psi', 6), 'Adv': ('End', 6)}}
        }

AGENT = {
    'Law Enforcement': {
        'Patroller': {'Surv': ('Int', 7), 'Qual': ('Int', 5), 'Adv': ('Edu', 7)},
        'Special Operations': {'Surv': ('End', 8), 'Qual': ('Int', 5), 'Adv': ('Int', 6)},
        'Customs': {'Surv': ('Dex', 6), 'Qual': ('Int', 5), 'Adv': ('Edu', 8)}},
    'Investigator': {
        'Private Detective': {'Surv': ('Int', 6), 'Qual': ('Int', 6), 'Adv': ('Soc', 8)},
        'Inspector': {'Surv': ('Edu', 7), 'Qual': ('Int', 6), 'Adv': ('Int', 7)},
        'Undercover Agent': {'Surv': ('Int', 8), 'Qual': ('Int', 6), 'Adv': ('Edu', 6)}},
    'Spy': {
        'Field Agent': {'Surv': ('Edu', 6), 'Qual': ('Int', 7), 'Adv': ('Soc', 8)},
        'Operative': {'Surv': ('Edu', 7), 'Qual': ('Int', 7), 'Adv': ('Int', 7)},
        'Infiltrator': {'Surv': ('Edu', 8), 'Qual': ('Int', 7), 'Adv': ('Int', 6)}},
    'Analyst': {
        'Political Officer': {'Surv': ('Soc', 6), 'Qual': ('Soc', 8), 'Adv': ('Soc', 7)},
        'Technical Expert': {'Surv': ('Int', 7), 'Qual': ('Soc', 8), 'Adv': ('Int', 6)},
        'Handler': {'Surv': ('Int', 7), 'Qual': ('Soc', 8), 'Adv': ('Soc', 7)}},
    'Corporate': {
        'Security': {'Surv': ('Int', 5), 'Qual': ('Int', 6), 'Adv': ('Int', 7)},
        'Espionage': {'Surv': ('Dex', 7), 'Qual': ('Int', 6), 'Adv': ('Int', 6)},
        'Bodyguard': {'Surv': ('End', 7), 'Qual': ('Int', 6), 'Adv': ('Soc', 6)}},
    'Bounty Hunter': {
        'Ship Tracer': {'Surv': ('End', 6), 'Qual': ('Int', 7), 'Adv': ('Soc', 7)},
        'Bondsman': {'Surv': ('End', 7), 'Qual': ('Int', 7), 'Adv': ('Int', 7)},
        'Thieftaker': {'Surv': ('Dex', 7), 'Qual': ('Int', 7), 'Adv': ('Int', 6)}}
    }

CHTHONIAN_STARS = {
    'Explorer': {
        'Exploration': {'Surv': ('End', 7), 'Qual': ('Int', 5), 'Adv': ('Edu', 7)},
        'Survey': {'Surv': ('End', 6), 'Qual': ('Int', 5), 'Adv': ('Int', 8)}},
    'Scholar': {
        'Physician': {'Surv': ('Edu', 4), 'Qual': ('Int', 6), 'Adv': ('Edu', 8)},
        'Scientist': {'Surv': ('Edu', 4), 'Qual': ('Int', 6), 'Adv': ('Int', 8)},
        'Field Researcher': {'Surv': ('End', 6), 'Qual': ('Int', 6), 'Adv': ('Int', 6)},
        'Occultist': {'Surv': ('Int', 6), 'Qual': ('Int', 6), 'Adv': ('Edu', 6)}},
    'Warden': {
        'Researcher': {'Surv': ('Int', 7), 'Qual': ('Int', 6), 'Adv': ('Int', 5)},
        'Enforcer': {'Surv': ('End', 6), 'Qual': ('Int', 6), 'Adv': ('Int', 5)},
        'Investigator': {'Surv': ('Int', 7), 'Qual': ('Int', 6), 'Adv': ('Int', 6)}},
    'Aristocrat': {
        'Administrator': {'Surv': ('Int', 4), 'Qual': ('Soc', 10), 'Adv': ('Edu', 6)},
        'Diplomat': {'Surv': ('Int', 5), 'Qual': ('Soc', 10), 'Adv': ('Soc', 7)},
        'Dilettante': {'Surv': ('Soc', 3), 'Qual': ('Soc', 10), 'Adv': ('Int', 8)}},
    }

SCOUNDREL = {
#   '': {
#       '': {'Surv': ('', ), 'Qual': ('', ), 'Adv': ('', )},
#       '': {'Surv': ('', ), 'Qual': ('', ), 'Adv': ('', )},
#       '': {'Surv': ('', ), 'Qual': ('', ), 'Adv': ('', )}},
    'Intruder': {
        'Hacker': {'Surv': ('Edu', 6), 'Qual': ('Int', 7), 'Adv': ('Int', 8)},
        'Burglar': {'Surv': ('End', 7), 'Qual': ('Int', 7), 'Adv': ('Dex', 7)},
        'Faceman': {'Surv': ('Edu', 8), 'Qual': ('Int', 7), 'Adv': ('Soc', 6)}},
    'Smuggler': {
        'Blockade Runner': {'Surv': ('Dex', 6), 'Qual': ('Edu', 6), 'Adv': ('Edu', 8)},
        'Bootlegger': {'Surv': ('End', 7), 'Qual': ('Edu', 6), 'Adv': ('Int', 7)},
        'Crew': {'Surv': ('Int', 6), 'Qual': ('Edu', 6), 'Adv': ('Edu', 8)}},
    'Organized Criminal': {
        'Assassin': {'Surv': ('End', 7), 'Qual': ('End', 8), 'Adv': ('Dex', 7)},
        'Enforcer': {'Surv': ('End', 8), 'Qual': ('End', 8), 'Adv': ('Str', 6)},
        'Co-ordinator': {'Surv': ('Edu', 6), 'Qual': ('End', 8), 'Adv': ('Int', 8)}},
    'Pirate': {
        'Corsair': {'Surv': ('Int', 7), 'Qual': ('Int', 7), 'Adv': ('Edu', 7)},
        'Boarder': {'Surv': ('End', 8), 'Qual': ('Int', 7), 'Adv': ('Int', 6)},
        'Jumpcusser': {'Surv': ('Dex', 6), 'Qual': ('Int', 7), 'Adv': ('Int', 8)}},
    'Scavenger': {
        'Wrecker': {'Surv': ('End', 7), 'Qual': ('Int', None), 'Adv': ('Edu', 7)},
        'Salvage Expert': {'Surv': ('Edu', 7), 'Qual': ('Int', None), 'Adv': ('Int', 7)},
        'Tomb Robber': {'Surv': ('End', 7), 'Qual': ('Int', None), 'Adv': ('Dex', 7)}},
    'Wanderer': {
        'Hitchhiker': {'Surv': ('Soc', 7), 'Qual': ('Int', None), 'Adv': ('Edu', 7)},
        'Vagabond': {'Surv': ('End', 7), 'Qual': ('Int', None), 'Adv': ('Int', 7)},
        'Bandit': {'Surv': ('End', 7), 'Qual': ('Int', None), 'Adv': ('Str', 7)}},
    'Barbarian': {
        'Warrior': {'Surv': ('End', 8), 'Qual': ('End', 7), 'Adv': ('Str', 6)},
        'Tribesman': {'Surv': ('End', 6), 'Qual': ('End', 7), 'Adv': ('Int', 8)},
        'Shaman': {'Surv': ('Int', 7), 'Qual': ('End', 7), 'Adv': ('Soc', 7)}},
    }

DILETTANTE = {
    'Adventurer': {
        'Explorer': {'Surv': ('Int', 6), 'Qual': ('End', 6), 'Adv': ('End', 6)},
        'Hunter': {'Surv': ('End', 7), 'Qual': ('End', 6), 'Adv': ('Dex', 5)},
        'Archaeologist': {'Surv': ('Edu', 5), 'Qual': ('End', 6), 'Adv': ('Int', 7)}},
    'Aristocrat': {
        'Courtier': {'Surv': ('Int', 7), 'Qual': ('Soc', 6), 'Adv': ('Soc', 5)},
        'Chevalier': {'Surv': ('Dex', 6), 'Qual': ('Soc', 6), 'Adv': ('Soc', 6)},
        'Paramour': {'Surv': ('Soc', 5), 'Qual': ('Soc', 6), 'Adv': ('End', 7)}},
    'Celebrity': {
        'Actor': {'Surv': ('Soc', 6), 'Qual': ('Soc', 7), 'Adv': ('Int', 6)},
        'Musician': {'Surv': ('Dex', 5), 'Qual': ('Soc', 7), 'Adv': ('Soc', 7)},
        'Luminary': {'Surv': ('Int', 7), 'Qual': ('Soc', 7), 'Adv': ('Edu', 5)}},
    'Competitor': {
        'Sportsman': {'Surv': ('End', 6), 'Qual': ('Int', 6), 'Adv': ('Str', 6)},
        'Athlete': {'Surv': ('Dex', 6), 'Qual': ('Str', 6), 'Adv': ('End', 6)},
        'Gamer': {'Surv': ('Int', 6), 'Qual': ('Int', 6), 'Adv': ('Edu', 6)}},
    'Connoisseur': {
        'Critic': {'Surv': ('Int', 7), 'Qual': ('Edu', 7), 'Adv': ('Edu', 5)},
        'Artisan': {'Surv': ('Dex', 5), 'Qual': ('Edu', 7), 'Adv': ('Soc', 7)},
        'Collector': {'Surv': ('Edu', 6), 'Qual': ('Edu', 7), 'Adv': ('Int', 6)}},
    'Dilettante': {
        'Wastrel': {'Surv': ('End', 5), 'Qual': ('Soc', 7), 'Adv': ('Int', 7)},
        'Socialite': {'Surv': ('Soc', 7), 'Qual': ('Soc', 7), 'Adv': ('End', 5)},
        'Philanthropist': {'Surv': ('Int', 6), 'Qual': ('Soc', 7), 'Adv': ('Soc', 6)}},
    'Humanitarian': {
        'Idealist': {'Surv': ('Soc', 5), 'Qual': ('Int', 6), 'Adv': ('Int', 7)},
        'Raconteur': {'Surv': ('Edu', 6), 'Qual': ('Int', 6), 'Adv': ('Soc', 6)},
        'Investigator': {'Surv': ('Int', 7), 'Qual': ('Int', 6), 'Adv': ('Edu', 5)}},
    }

DRAFT = ["Army", "Navy", "Marines"]

FALLBACK_CAREERS = ["Drifter"] + DRAFT

WORLDS = {"Mercury": ["Admin", "Vacc Suit"],
          "Venus": ["Admin", "Survival"],
          "Earth": ["Computers", "Streetwise"],
          "Mars": ["Computers", "Survival"],
          "Callisto": ["Vacc Suit", "Zero-G"],
          "Europa": ["Computers", "Life Science", "Space Science"],
          "Ganymede": ["Carouse", "Streetwise"],
          "Enceladus": ["Life Science", "Space Science", "Steward"],
          "Titan": ["Computers", "Streetwise"],
          "Uranus": ["Admin", "Vacc Suit"],
          "Neptune": ["Recon", "Vacc Suit"],
          "Kuiper Belt": ["Recon", "Vacc Suit"]}

WORLD_ADJ = {'Callisto': 'Callistan',
             'Earth': 'Earther',
             'Enceladus': 'Enceladian',
             'Europa': 'Europan',
             'Ganymede': 'Ganymedan',
             'Kuiper Belt': 'Belter',
             'Mars': 'Martian',
             'Mercury': 'Mercurian',
             'Neptune': 'Neptunian',
             'Titan': 'Titanian',
             'Uranus': 'Uranian',
             'Venus': 'Venusian'}

EDU_SKILLS = [("Admin", 0), ("Advocate", 0), ("Art", 0), ("Carouse", 0),
              ("Comms", 0), ("Computers", 0), ("Drive", 0), ("Engineer", 0),
              ("Language", 0), ("Medic", 0), ("Physical Science", 0),
              ("Life Science", 0), ("Social Science", 0),
              ("Space Science", 0), ("Trade", 0)]

SKILL_TYPES = {"BT": 0, "Personal Development": 1, "Service": 2,
               "Specialization": 3, "Advanced Education": 4, "Officer": 5}

SKILLS = {
    # (Career, Spec): (
    #   (Basic Training x6),
    #   (Personal Development x6),
    #   (Service Skills x6),
    #   (Specialist x6),
    #   (Advanced Edu x6),
    #   (Officer Skills x6))

    ("Warden", "Enforcer"): (
        ("Streetwise", 0), ("Drive", 0), ("Investigate", 0), ("Computers", 0), ("Recon", 0), ("Gun Combat", 0),
        ("Gun Combat", 0), ("Dex", 1), ("End", 1), ("Melee", 0), ("Int", 1), ("Athletics", 0),
        ("Streetwise", 0), ("Drive", 0), ("Investigate", 0), ("Computers", 0), ("Recon", 0), ("Gun Combat", 0),
        ("Advocate", 0), ("Melee", 0), ("Gun Combat", 0), ("Recon", 0), ("Stealth", 0), ("Occult", 0),
        ("Advocate", 0), ("Comms", 0), ("Computers", 0), ("Medic", 0), ("Stealth", 0), ("Remote Operations", 0)),
    ("Warden", "Investigator"): (
        ("Streetwise", 0), ("Drive", 0), ("Investigate", 0), ("Computers", 0), ("Recon", 0), ("Gun Combat", 0),
        ("Gun Combat", 0), ("Dex", 1), ("End", 1), ("Melee", 0), ("Int", 1), ("Athletics", 0),
        ("Streetwise", 0), ("Drive", 0), ("Investigate", 0), ("Computers", 0), ("Recon", 0), ("Gun Combat", 0),
        ("Investigate", 0), ("Recon", 0), ("Occult", 0), ("Stealth", 0), ("Persuade", 0), ("Deception", 0),
        ("Advocate", 0), ("Comms", 0), ("Computers", 0), ("Medic", 0), ("Stealth", 0), ("Remote Operations", 0)),
    ("Warden", "Researcher"): (
        ("Streetwise", 0), ("Drive", 0), ("Investigate", 0), ("Computers", 0), ("Recon", 0), ("Gun Combat", 0),
        ("Gun Combat", 0), ("Dex", 1), ("End", 1), ("Melee", 0), ("Int", 1), ("Athletics", 0),
        ("Streetwise", 0), ("Drive", 0), ("Investigate", 0), ("Computers", 0), ("Recon", 0), ("Gun Combat", 0),
        ("Occult", 0), ("Investigate", 0), ("Computers", 0), ("Any Science", 0), ("Jack of all Trades", 0), ("Language", 0),
        ("Advocate", 0), ("Comms", 0), ("Computers", 0), ("Medic", 0), ("Stealth", 0), ("Remote Operations", 0)),
    ("Agent", "Law Enforcement"): (("Streetwise", 0), ("Drive", 0), ("Investigate", 0),
        ("Computers", 0), ("Recon", 0), ("Gun Combat", 0), ("Gun Combat", 0),
        ("Dex", 1), ("End", 1), ("Melee", 0), ("Int", 1),
        ("Athletics", 0), ("Streetwise", 0), ("Drive", 0), ("Investigate", 0),
        ("Computers", 0), ("Recon", 0), ("Gun Combat", 0), ("Investigate", 0),
        ("Recon", 0), ("Streetwise", 0), ("Stealth", 0), ("Melee", 0), ("Advocate", 0),
        ("Advocate", 0), ("Comms", 0), ("Computers", 0), ("Medic", 0), ("Stealth", 0),
        ("Remote Operations", 0)),
    ("Agent", "Intelligence"): (("Streetwise", 0), ("Drive", 0), ("Investigate", 0),
        ("Computers", 0), ("Recon", 0), ("Gun Combat", 0), ("Gun Combat", 0),
        ("Dex", 1), ("End", 1), ("Melee", 0), ("Int", 1),
        ("Athletics", 0), ("Streetwise", 0), ("Drive", 0), ("Investigate", 0),
        ("Computers", 0), ("Recon", 0), ("Gun Combat", 0), ("Investigate", 0),
        ("Recon", 0), ("Comms", 0), ("Stealth", 0), ("Persuade", 0), ("Deception", 0),
        ("Advocate", 0), ("Comms", 0), ("Computers", 0), ("Medic", 0), ("Stealth", 0),
        ("Remote Operations", 0)),
    ("Agent", "Corporate"): (("Streetwise", 0), ("Drive", 0), ("Investigate", 0),
        ("Computers", 0), ("Recon", 0), ("Gun Combat", 0), ("Gun Combat", 0),
        ("Dex", 1), ("End", 1), ("Melee", 0), ("Int", 1),
        ("Athletics", 0), ("Streetwise", 0), ("Drive", 0), ("Investigate", 0),
        ("Computers", 0), ("Recon", 0), ("Gun Combat", 0), ("Investigate", 0),
        ("Computers", 0), ("Stealth", 0), ("Gun Combat", 0), ("Deception", 0),
        ("Streetwise", 0), ("Advocate", 0), ("Comms", 0), ("Computers", 0), ("Medic", 0),
        ("Stealth", 0), ("Remote Operations", 0)),
    ("Army", "Support"): (("Drive", 0), ("Athletics", 0), ("Gun Combat", 0),
        ("Recon", 0), ("Melee", 0), ("Heavy Weapons", 0), ("Str", 1),
        ("Dex", 1), ("End", 1), ("Gambler", 0), ("Medic", 0),
        ("Melee (unarmed)", 0), ("Drive", 0), ("Athletics", 0), ("Gun Combat", 0),
        ("Recon", 0), ("Melee", 0), ("Heavy Weapons", 0), ("Mechanic", 0),
        ("Drive", 0), ("Flyer", 0), ("Explosives", 0), ("Comms", 0), ("Medic", 0),
        ("Comms", 0), ("Sensors", 0), ("Navigation", 0), ("Explosives", 0),
        ("Engineer", 0), ("Survival", 0), ("Tactics (military)", 0), ("Leadership", 0),
        ("Advocate", 0), ("Diplomat", 0), ("Tactics (military)", 0), ("Admin", 0)),
    ("Army", "Infantry"): (("Drive", 0), ("Athletics", 0), ("Gun Combat", 0),
        ("Recon", 0), ("Melee", 0), ("Heavy Weapons", 0), ("Str", 1),
        ("Dex", 1), ("End", 1), ("Gambler", 0), ("Medic", 0),
        ("Melee (unarmed)", 0), ("Drive", 0), ("Athletics", 0), ("Gun Combat", 0), ("Recon", 0),
        ("Melee", 0), ("Heavy Weapons", 0), ("Gun Combat", 0), ("Melee", 0),
        ("Heavy Weapons", 0), ("Stealth", 0), ("Athletics", 0), ("Recon", 0), ("Comms", 0),
        ("Sensors", 0), ("Navigation", 0), ("Explosives", 0), ("Engineer", 0),
        ("Survival", 0), ("Tactics (military)", 0), ("Leadership", 0), ("Advocate", 0),
        ("Diplomat", 0), ("Tactics (military)", 0), ("Admin", 0)),
    ("Army", "Cavalry"): (("Drive", 0), ("Athletics", 0), ("Gun Combat", 0),
        ("Recon", 0), ("Melee", 0), ("Heavy Weapons", 0), ("Str", 1),
        ("Dex", 1), ("End", 1), ("Gambler", 0), ("Medic", 0),
        ("Melee (unarmed)", 0), ("Drive", 0), ("Athletics", 0), ("Gun Combat", 0), ("Recon", 0),
        ("Melee", 0), ("Heavy Weapons", 0), ("Mechanic", 0), ("Drive", 0), ("Flyer", 0),
        ("Recon", 0), ("Gunner", 0), ("Sensors", 0), ("Comms", 0), ("Sensors", 0),
        ("Navigation", 0), ("Explosives", 0), ("Engineer", 0), ("Survival", 0),
        ("Tactics (military)", 0), ("Leadership", 0), ("Advocate", 0), ("Diplomat", 0),
        ("Tactics (military)", 0), ("Admin", 0)),
    ("Citizen", "Corporate"): (("Advocate", 0), ("Admin", 0), ("Broker", 0),
        ("Computers", 0), ("Diplomat", 0), ("Leadership", 0), ("Edu", 1),
        ("Int", 1), ("Carouse", 0), ("Gambler", 0), ("Drive", 0),
        ("Jack of all Trades", 0), ("Drive", 0), ("Flyer", 0), ("Streetwise", 0), ("Melee", 0),
        ("Steward", 0), ("Trade", 0), ("Advocate", 0), ("Admin", 0), ("Broker", 0),
        ("Computers", 0), ("Diplomat", 0), ("Leadership", 0), ("Art", 0),
        ("Advocate", 0), ("Diplomat", 0), ("Language", 0), ("Computers", 0),
        ("Medic", 0)),
    ("Citizen", "Worker"): (("Drive", 0), ("Mechanic", 0), ("Trade", 0),
        ("Engineer", 0), ("Trade", 0), ("Any Science", 0), ("Edu", 1),
        ("Int", 1), ("Carouse", 0), ("Gambler", 0), ("Drive", 0),
        ("Jack of all Trades", 0), ("Drive", 0), ("Flyer", 0), ("Streetwise", 0), ("Melee", 0),
        ("Steward", 0), ("Trade", 0), ("Drive", 0), ("Mechanic", 0), ("Trade", 0),
        ("Engineer", 0), ("Trade", 0), ("Any Science", 0), ("Art", 0),
        ("Advocate", 0), ("Diplomat", 0), ("Language", 0), ("Computers", 0),
        ("Medic", 0)),
    ("Citizen", "Colonist"): (("Animals", 0), ("Athletics", 0),
        ("Jack of all Trades", 0), ("Drive", 0), ("Survival", 0), ("Recon", 0), ("Edu", 1),
        ("Int", 1), ("Carouse", 0), ("Gambler", 0), ("Drive", 0),
        ("Jack of all Trades", 0), ("Drive", 0), ("Flyer", 0), ("Streetwise", 0), ("Melee", 0),
        ("Steward", 0), ("Trade", 0), ("Animals", 0), ("Athletics", 0),
        ("Jack of all Trades", 0), ("Drive", 0), ("Survival", 0), ("Recon", 0), ("Art", 0),
        ("Advocate", 0), ("Diplomat", 0), ("Language", 0), ("Computers", 0), ("Medic", 0)),
    ("Drifter", "Barbarian"): (
        ("Animals", 0), ("Carouse", 0), ("Melee", 0), ("Stealth", 0), ("Seafarer", 0), ("Survival", 0),
        ("Str", 1), ("End", 1), ("Dex", 1), ("Jack of all Trades", 0), ("End", 1), ("Int", 1),
        ("Athletics", 0), ("Melee (unarmed)", 0), ("Recon", 0), ("Streetwise", 0), ("Stealth", 0), ("Survival", 0),
        ("Animals", 0), ("Carouse", 0), ("Melee (blade)", 0), ("Stealth", 0), ("Seafarer", 0), ("Survival", 0)),
    ("Drifter", "Wanderer"): (
        ("Athletics", 0), ("Deception", 0), ("Recon", 0), ("Stealth", 0), ("Streetwise", 0), ("Survival", 0),
        ("Str", 1), ("End", 1), ("Dex", 1), ("Jack of all Trades", 0),("End", 1), ("Int", 1),
        ("Athletics", 0), ("Melee (unarmed)", 0), ("Recon", 0), ("Streetwise", 0), ("Stealth", 0), ("Survival", 0),
        ("Athletics", 0), ("Deception", 0), ("Recon", 0), ("Stealth", 0), ("Streetwise", 0), ("Survival", 0)),
    ("Drifter", "Scavenger"): (
        ("Pilot", 0), ("Mechanic", 0), ("Astrogation", 0), ("Vacc Suit", 0), ("Zero-G", 0), ("Gun Combat", 0),
        ("Str", 1), ("End", 1), ("Dex", 1), ("Jack of all Trades", 0), ("End", 1), ("Int", 1),
        ("Athletics", 0), ("Melee (unarmed)", 0), ("Recon", 0), ("Streetwise", 0), ("Stealth", 0), ("Survival", 0),
        ("Pilot (small craft)", 0), ("Mechanic", 0), ("Astrogation", 0), ("Vacc Suit", 0), ("Zero-G", 0), ("Gun Combat", 0)),
    ("Entertainer", "Artist"): (("Any Art", 0), ("Any Art'", 0), ("Carouse", 0),
        ("Deception", 0), ("Persuade", 0), ("Steward", 0), ("Dex", 1),
        ("Int", 1), ("Soc", 1), ("Edu", 1), ("Carouse", 0),
        ("Stealth", 0), ("Any Art", 0), ("Any Art", 0), ("Carouse", 0), ("Deception", 0),
        ("Persuade", 0), ("Steward", 0), ("Any Art", 0), ("Carouse", 0),
        ("Computers", 0), ("Gambler", 0), ("Persuade", 0), ("Trade", 0),
        ("Advocate", 0), ("Art", 0), ("Deception", 0), ("Any Science", 0),
        ("Streetwise", 0), ("Diplomat", 0)),
    ("Entertainer", "Journalist"): (("Any Art", 0), ("Any Art'", 0), ("Carouse", 0),
        ("Deception", 0), ("Persuade", 0), ("Steward", 0), ("Dex", 1),
        ("Int", 1), ("Soc", 1), ("Edu", 1), ("Carouse", 0),
        ("Stealth", 0), ("Any Art", 0), ("Any Art", 0), ("Carouse", 0), ("Deception", 0),
        ("Persuade", 0), ("Steward", 0), ("Art (writing) or Art (holography)", 0),
        ("Comms", 0), ("Computers", 0), ("Investigate", 0), ("Recon", 0),
        ("Streetwise", 0), ("Advocate", 0), ("Art", 0), ("Deception", 0),
        ("Any Science", 0), ("Streetwise", 0), ("Diplomat", 0)),
    ("Entertainer", "Performer"): (
        ("Any Art", 0), ("Any Art'", 0), ("Carouse", 0), ("Deception", 0), ("Persuade", 0), ("Steward", 0),
        ("Dex", 1), ("Int", 1), ("Soc", 1), ("Edu", 1), ("Carouse", 0), ("Stealth", 0),
        ("Any Art", 0), ("Any Art", 0), ("Carouse", 0), ("Deception", 0), ("Persuade", 0), ("Steward", 0),
        ("Art (acting) or Art (dance) or Art (instrument)", 0),
        ("Athletics (coordination) or Athletics (endurance)", 0),
        ("Carouse", 0), ("Deception", 0), ("Stealth", 0), ("Streetwise", 0),
        ("Advocate", 0), ("Art", 0), ("Deception", 0), ("Any Science", 0), ("Streetwise", 0), ("Diplomat", 0)),
    ("Marines", "Support"): (
        ("Athletics", 0), ("Battle Dress", 0), ("Tactics", 0), ("Heavy Weapons", 0), ("Gun Combat", 0), ("Stealth", 0),
        ("Str", 1), ("Dex", 1), ("End", 1), ("Gambler", 0), ("Melee (unarmed)", 0), ("Melee (armed)", 0),
        ("Athletics", 0), ("Battle Dress", 0), ("Tactics", 0), ("Heavy Weapons", 0), ("Gun Combat", 0), ("Stealth", 0),
        ("Comms", 0), ("Mechanic", 0), ("Drive or Flyer", 0), ("Medic", 0), ("Heavy Weapons", 0), ("Gun Combat", 0),
        ("Medic", 0), ("Survival", 0), ("Explosives", 0), ("Engineer", 0), ("Pilot", 0), ("Medic", 0),
        ("Leadership", 0), ("Tactics", 0), ("Admin", 0), ("Advocate", 0), ("Battle Dress", 0), ("Leadership", 0)),
    ("Marines", "Star Marines"): (("Athletics", 0), ("Battle Dress", 0),
        ("Tactics", 0), ("Heavy Weapons", 0), ("Gun Combat", 0), ("Stealth", 0),
        ("Str", 1), ("Dex", 1), ("End", 1), ("Gambler", 0),
        ("Melee (unarmed)", 0), ("Melee (armed)", 0), ("Athletics", 0), ("Battle Dress", 0),
        ("Tactics", 0), ("Heavy Weapons", 0), ("Gun Combat", 0), ("Stealth", 0),
        ("Battle Dress", 0), ("Zero-G", 0), ("Gunner", 0), ("Melee (blade)", 0),
        ("Sensors", 0), ("Gun Combat", 0), ("Medic", 0), ("Survival", 0),
        ("Explosives", 0), ("Engineer", 0), ("Pilot", 0), ("Medic", 0),
        ("Leadership", 0), ("Tactics", 0), ("Admin", 0), ("Advocate", 0),
        ("Battle Dress", 0), ("Leadership", 0)),
    ("Marines", "Ground Assault"): (("Athletics", 0), ("Battle Dress", 0),
        ("Tactics", 0), ("Heavy Weapons", 0), ("Gun Combat", 0), ("Stealth", 0),
        ("Str", 1), ("Dex", 1), ("End", 1), ("Gambler", 0),
        ("Melee (unarmed)", 0), ("Melee (armed)", 0), ("Athletics", 0), ("Battle Dress", 0),
        ("Tactics", 0), ("Heavy Weapons", 0), ("Gun Combat", 0), ("Stealth", 0),
        ("Battle Dress", 0), ("Heavy Weapons", 0), ("Recon", 0),
        ("Melee (blade)", 0), ("Tactics (military)", 0), ("Gun Combat", 0), ("Medic", 0),
        ("Survival", 0), ("Explosives", 0), ("Engineer", 0), ("Pilot", 0),
        ("Medic", 0), ("Leadership", 0), ("Tactics", 0), ("Admin", 0),
        ("Advocate", 0), ("Battle Dress", 0), ("Leadership", 0)),
    ("Merchant", "Merchant Marine"): (("Drive", 0), ("Vacc Suit", 0), ("Broker", 0),
        ("Steward", 0), ("Comms", 0), ("Persuade", 0), ("Str", 1),
        ("Dex", 1), ("End", 1), ("Int", 1),
        ("Melee (blade)", 0), ("Streetwise", 0), ("Drive", 0), ("Vacc Suit", 0),
        ("Broker", 0), ("Steward", 0), ("Comms", 0), ("Persuade", 0),
        ("Pilot (spacecraft) or Pilot (capital ships)", 0), ("Vacc Suit", 0), ("Zero-G", 0),
        ("Mechanic", 0), ("Engineer", 0), ("Gunner", 0), ("Social Science", 0),
        ("Astrogation", 0), ("Computers", 0), ("Pilot", 0), ("Admin", 0),
        ("Advocate", 0)),
    ("Merchant", "Free Trader"): (("Drive", 0), ("Vacc Suit", 0), ("Broker", 0),
        ("Steward", 0), ("Comms", 0), ("Persuade", 0), ("Str", 1),
        ("Dex", 1), ("End", 1), ("Int", 1),
        ("Melee (blade)", 0), ("Streetwise", 0), ("Drive", 0), ("Vacc Suit", 0),
        ("Broker", 0), ("Steward", 0), ("Comms", 0), ("Persuade", 0),
        ("Pilot (spacecraft)", 0), ("Vacc Suit", 0), ("Zero-G", 0), ("Mechanic", 0),
        ("Engineer", 0), ("Sensors", 0), ("Social Science", 0), ("Astrogation", 0),
        ("Computers", 0), ("Pilot", 0), ("Admin", 0), ("Advocate", 0)),
    ("Merchant", "Broker"): (("Drive", 0), ("Vacc Suit", 0), ("Broker", 0),
        ("Steward", 0), ("Comms", 0), ("Persuade", 0), ("Str", 1),
        ("Dex", 1), ("End", 1), ("Int", 1),
        ("Melee (blade)", 0), ("Streetwise", 0), ("Drive", 0), ("Vacc Suit", 0),
        ("Broker", 0), ("Steward", 0), ("Comms", 0), ("Persuade", 0), ("Admin", 0),
        ("Advocate", 0), ("Broker", 0), ("Streetwise", 0), ("Deception", 0),
        ("Persuade", 0), ("Social Science", 0), ("Astrogation", 0),
        ("Computers", 0), ("Pilot", 0), ("Admin", 0), ("Advocate", 0)),
    ("Navy", "Line/Crew"): (("Pilot", 0), ("Vacc Suit", 0), ("Zero-G", 0),
        ("Gunner", 0), ("Mechanic", 0), ("Gun Combat", 0), ("Str", 1),
        ("Dex", 1), ("End", 1), ("Int", 1), ("Edu", 1),
        ("Soc", 1), ("Pilot", 0), ("Vacc Suit", 0), ("Zero-G", 0), ("Gunner", 0),
        ("Mechanic", 0), ("Gun Combat", 0), ("Comms", 0), ("Mechanic", 0),
        ("Gun Combat", 0), ("Sensors", 0), ("Melee", 0), ("Vacc Suit", 0),
        ("Remote Operations", 0), ("Astrogation", 0), ("Engineer", 0), ("Computers", 0),
        ("Navigation", 0), ("Admin", 0), ("Leadership", 0), ("Tactics (naval)", 0),
        ("Pilot", 0), ("Melee (blade)", 0), ("Admin", 0), ("Tactics (naval)", 0)),
    ("Navy", "Engineering/Gunnery"): (("Pilot", 0), ("Vacc Suit", 0), ("Zero-G", 0),
        ("Gunner", 0), ("Mechanic", 0), ("Gun Combat", 0), ("Str", 1),
        ("Dex", 1), ("End", 1), ("Int", 1), ("Edu", 1),
        ("Soc", 1), ("Pilot", 0), ("Vacc Suit", 0), ("Zero-G", 0), ("Gunner", 0),
        ("Mechanic", 0), ("Gun Combat", 0), ("Engineer", 0), ("Mechanic", 0),
        ("Sensors", 0), ("Engineer", 0), ("Gunner", 0), ("Computers", 0),
        ("Remote Operations", 0), ("Astrogation", 0), ("Engineer", 0), ("Computers", 0),
        ("Navigation", 0), ("Admin", 0), ("Leadership", 0), ("Tactics (naval)", 0),
        ("Pilot", 0), ("Melee (blade)", 0), ("Admin", 0), ("Tactics (naval)", 0)),
    ("Navy", "Flight"): (("Pilot", 0), ("Vacc Suit", 0), ("Zero-G", 0), ("Gunner", 0),
        ("Mechanic", 0), ("Gun Combat", 0), ("Str", 1), ("Dex", 1),
        ("End", 1), ("Int", 1), ("Edu", 1), ("Soc", 1),
        ("Pilot", 0), ("Vacc Suit", 0), ("Zero-G", 0), ("Gunner", 0),
        ("Mechanic", 0), ("Gun Combat", 0), ("Pilot", 0), ("Flyer", 0),
        ("Gunner", 0), ("Pilot (small craft)", 0), ("Astrogation", 0),
        ("Zero-G", 0), ("Remote Operations", 0), ("Astrogation", 0),
        ("Engineer", 0), ("Computers", 0), ("Navigation", 0), ("Admin", 0),
        ("Leadership", 0), ("Tactics (naval)", 0), ("Pilot", 0),
        ("Melee (blade)", 0), ("Admin", 0), ("Tactics (naval)", 0)),
    ("Nobility", "Administrator"): (("Admin", 0), ("Advocate", 0), ("Comms", 0),
        ("Diplomat", 0), ("Investigate", 0), ("Persuade", 0), ("Carouse", 0),
        ("Edu", 1), ("Deception", 0), ("Dex", 1), ("Melee (blade)", 0),
        ("Soc", 1), ("Admin", 0), ("Advocate", 0), ("Comms", 0), ("Diplomat", 0),
        ("Investigate", 0), ("Persuade", 0), ("Admin", 0), ("Advocate", 0),
        ("Broker", 0), ("Diplomat", 0), ("Leadership", 0), ("Persuade", 0),
        ("Admin", 0), ("Advocate", 0), ("Language", 0), ("Leadership", 0),
        ("Diplomat", 0), ("Computers", 0)),
    ("Nobility", "Diplomat"): (("Admin", 0), ("Advocate", 0), ("Comms", 0),
        ("Diplomat", 0), ("Investigate", 0), ("Persuade", 0), ("Carouse", 0),
        ("Edu", 1), ("Deception", 0), ("Dex", 1), ("Melee (blade)", 0),
        ("Soc", 1), ("Admin", 0), ("Advocate", 0), ("Comms", 0), ("Diplomat", 0),
        ("Investigate", 0), ("Persuade", 0), ("Advocate", 0), ("Carouse", 0),
        ("Comms", 0), ("Steward", 0), ("Diplomat", 0), ("Deception", 0),
        ("Admin", 0), ("Advocate", 0), ("Language", 0), ("Leadership", 0),
        ("Diplomat", 0), ("Computers", 0)),
    ("Nobility", "Dilettante"): (("Admin", 0), ("Advocate", 0), ("Comms", 0),
        ("Diplomat", 0), ("Investigate", 0), ("Persuade", 0), ("Carouse", 0),
        ("Edu", 1), ("Deception", 0), ("Dex", 1), ("Melee (blade)", 0),
        ("Soc", 1), ("Admin", 0), ("Advocate", 0), ("Comms", 0), ("Diplomat", 0),
        ("Investigate", 0), ("Persuade", 0), ("Carouse", 0), ("Deception", 0),
        ("Flyer", 0), ("Streetwise", 0), ("Gambler", 0), ("Jack of all Trades", 0),
        ("Admin", 0), ("Advocate", 0), ("Language", 0), ("Leadership", 0),
        ("Diplomat", 0), ("Computers", 0)),
    ("Aristocrat", "Administrator"): (("Admin", 0), ("Advocate", 0), ("Comms", 0),
        ("Diplomat", 0), ("Investigate", 0), ("Persuade", 0), ("Carouse", 0),
        ("Edu", 1), ("Deception", 0), ("Dex", 1), ("Melee (blade)", 0),
        ("Soc", 1), ("Admin", 0), ("Advocate", 0), ("Comms", 0), ("Diplomat", 0),
        ("Investigate", 0), ("Persuade", 0), ("Admin", 0), ("Advocate", 0),
        ("Broker", 0), ("Diplomat", 0), ("Leadership", 0), ("Persuade", 0),
        ("Admin", 0), ("Advocate", 0), ("Language", 0), ("Leadership", 0),
        ("Diplomat", 0), ("Computers", 0)),
    ("Aristocrat", "Diplomat"): (("Admin", 0), ("Advocate", 0), ("Comms", 0),
        ("Diplomat", 0), ("Investigate", 0), ("Persuade", 0), ("Carouse", 0),
        ("Edu", 1), ("Deception", 0), ("Dex", 1), ("Melee (blade)", 0),
        ("Soc", 1), ("Admin", 0), ("Advocate", 0), ("Comms", 0), ("Diplomat", 0),
        ("Investigate", 0), ("Persuade", 0), ("Advocate", 0), ("Carouse", 0),
        ("Comms", 0), ("Steward", 0), ("Diplomat", 0), ("Deception", 0),
        ("Admin", 0), ("Advocate", 0), ("Language", 0), ("Leadership", 0),
        ("Diplomat", 0), ("Computers", 0)),
    ("Aristocrat", "Dilettante"): (("Admin", 0), ("Advocate", 0), ("Comms", 0),
        ("Diplomat", 0), ("Investigate", 0), ("Persuade", 0), ("Carouse", 0),
        ("Edu", 1), ("Deception", 0), ("Dex", 1), ("Melee (blade)", 0),
        ("Soc", 1), ("Admin", 0), ("Advocate", 0), ("Comms", 0), ("Diplomat", 0),
        ("Investigate", 0), ("Persuade", 0), ("Carouse", 0), ("Deception", 0),
        ("Flyer", 0), ("Streetwise", 0), ("Gambler", 0), ("Jack of all Trades", 0),
        ("Admin", 0), ("Advocate", 0), ("Language", 0), ("Leadership", 0),
        ("Diplomat", 0), ("Computers", 0)),
    ("Rogue", "Thief"): (("Deception", 0), ("Recon", 0), ("Athletics", 0),
        ("Gun Combat", 0), ("Stealth", 0), ("Streetwise", 0), ("Carouse", 0), ("Dex", 1),
        ("End", 1), ("Gambler", 0), ("Melee", 0), ("Gun Combat", 0), ("Deception", 0),
        ("Recon", 0), ("Athletics", 0), ("Gun Combat", 0), ("Stealth", 0), ("Streetwise", 0),
        ("Stealth", 0), ("Computers", 0), ("Remote Operations", 0), ("Streetwise", 0),
        ("Deception", 0), ("Athletics (co-ordination)", 0), ("Computers", 0), ("Comms", 0),
        ("Medic", 0), ("Investigate", 0), ("Persuade", 0), ("Advocate", 0)),
    ("Rogue", "Enforcer"): (("Deception", 0), ("Recon", 0), ("Athletics", 0),
        ("Gun Combat", 0), ("Stealth", 0), ("Streetwise", 0), ("Carouse", 0), ("Dex", 1),
        ("End", 1), ("Gambler", 0), ("Melee", 0), ("Gun Combat", 0), ("Deception", 0),
        ("Recon", 0), ("Athletics", 0), ("Gun Combat", 0), ("Stealth", 0), ("Streetwise", 0),
        ("Gun Combat", 0), ("Melee", 0), ("Streetwise", 0), ("Persuade", 0),
        ("Athletics", 0), ("Drive", 0), ("Computers", 0), ("Comms", 0), ("Medic", 0),
        ("Investigate", 0), ("Persuade", 0), ("Advocate", 0)),
    ("Rogue", "Pirate"): (("Deception", 0), ("Recon", 0), ("Athletics", 0),
        ("Gun Combat", 0), ("Stealth", 0), ("Streetwise", 0), ("Carouse", 0), ("Dex", 1),
        ("End", 1), ("Gambler", 0), ("Melee", 0), ("Gun Combat", 0), ("Deception", 0),
        ("Recon", 0), ("Athletics", 0), ("Gun Combat", 0), ("Stealth", 0), ("Streetwise", 0),
        ("Pilot", 0), ("Astrogation", 0), ("Gunner", 0), ("Engineer", 0), ("Vacc Suit", 0),
        ("Melee (blade)", 0), ("Computers", 0), ("Comms", 0), ("Medic", 0),
        ("Investigate", 0), ("Persuade", 0), ("Advocate", 0)),
    ("Scholar", "Field Researcher"): (("Comms", 0), ("Computers", 0), ("Diplomat", 0),
        ("Medic", 0), ("Investigate", 0), ("Any Science", 0), ("Int", 1),
        ("Edu", 1), ("Soc", 1), ("Dex", 1), ("End", 1),
        ("Computers", 0), ("Comms", 0), ("Computers", 0), ("Diplomat", 0),
        ("Medic", 0), ("Investigate", 0), ("Any Science", 0), ("Sensors", 0),
        ("Diplomat", 0), ("Language", 0), ("Survival", 0), ("Investigate", 0),
        ("Any Science", 0), ("Art", 0), ("Advocate", 0), ("Computers", 0), ("Language", 0),
        ("Engineer", 0), ("Any Science", 0)),
    ("Scholar", "Scientist"): (("Comms", 0), ("Computers", 0), ("Diplomat", 0),
        ("Medic", 0), ("Investigate", 0), ("Any Science", 0), ("Int", 1),
        ("Edu", 1), ("Soc", 1), ("Dex", 1), ("End", 1),
        ("Computers", 0), ("Comms", 0), ("Computers", 0), ("Diplomat", 0),
        ("Medic", 0), ("Investigate", 0), ("Any Science", 0), ("Admin", 0),
        ("Engineer", 0), ("Any Science", 0), ("Sensors", 0), ("Computers", 0),
        ("Any Science", 0), ("Art", 0), ("Advocate", 0), ("Computers", 0), ("Language", 0),
        ("Engineer", 0), ("Any Science", 0)),
    ("Scholar", "Physician"): (("Comms", 0), ("Computers", 0), ("Diplomat", 0),
        ("Medic", 0), ("Investigate", 0), ("Any Science", 0), ("Int", 1),
        ("Edu", 1), ("Soc", 1), ("Dex", 1), ("End", 1),
        ("Computers", 0), ("Comms", 0), ("Computers", 0), ("Diplomat", 0),
        ("Medic", 0), ("Investigate", 0), ("Any Science", 0), ("Medic", 0),
        ("Comms", 0), ("Investigate", 0), ("Medic", 0), ("Persuade", 0),
        ("Any Science", 0), ("Art", 0), ("Advocate", 0), ("Computers", 0), ("Language", 0),
        ("Engineer", 0), ("Any Science", 0)),
    ("Scholar", "Occultist"): (("Comms", 0), ("Computers", 0), ("Diplomat", 0),
        ("Medic", 0), ("Investigate", 0), ("Any Science", 0), ("Int", 1),
        ("Edu", 1), ("Soc", 1), ("Dex", 1), ("End", 1),
        ("Computers", 0), ("Comms", 0), ("Computers", 0), ("Diplomat", 0),
        ("Medic", 0), ("Investigate", 0), ("Any Science", 0), ("Investigate", 0),
        ("Occult", 0), ("Any Science", 0), ("Computers", 0), ("Language", 0), ("Occult", 0),
        ("Art", 0), ("Advocate", 0), ("Computers", 0), ("Language", 0),
        ("Engineer", 0), ("Any Science", 0)),
    ("Scout", "Courier"): (("Pilot", 0), ("Survival", 0), ("Mechanic", 0),
        ("Astrogation", 0), ("Comms", 0), ("Gun Combat", 0), ("Str", 1),
        ("Dex", 1), ("End", 1), ("Int", 1), ("Edu", 1),
        ("Jack of all Trades", 0), ("Pilot (spacecraft) or Pilot (small craft)", 0),
        ("Survival", 0), ("Mechanic", 0), ("Astrogation", 0), ("Comms", 0),
        ("Gun Combat", 0), ("Comms", 0), ("Sensors", 0), ("Pilot (spacecraft)", 0),
        ("Vacc Suit", 0), ("Zero-G", 0), ("Astrogation", 0), ("Medic", 0),
        ("Navigation", 0), ("Engineer", 0), ("Computers", 0), ("Space Science", 0),
        ("Jack of all Trades", 0)),
    ("Scout", "Survey"): (("Pilot", 0), ("Survival", 0), ("Mechanic", 0),
        ("Astrogation", 0), ("Comms", 0), ("Gun Combat", 0), ("Str", 1),
        ("Dex", 1), ("End", 1), ("Int", 1), ("Edu", 1),
        ("Jack of all Trades", 0), ("Pilot (spacecraft) or Pilot (small craft)", 0),
        ("Survival", 0), ("Mechanic", 0), ("Astrogation", 0), ("Comms", 0),
        ("Gun Combat", 0), ("Sensors", 0), ("Persuade", 0), ("Pilot (small craft)", 0),
        ("Navigation", 0), ("Diplomat", 0), ("Streetwise", 0), ("Medic", 0),
        ("Navigation", 0), ("Engineer", 0), ("Computers", 0), ("Space Science", 0),
        ("Jack of all Trades", 0)),
    ("Scout", "Exploration"): (("Pilot", 0), ("Survival", 0), ("Mechanic", 0),
        ("Astrogation", 0), ("Comms", 0), ("Gun Combat", 0), ("Str", 1),
        ("Dex", 1), ("End", 1), ("Int", 1), ("Edu", 1),
        ("Jack of all Trades", 0), ("Pilot (spacecraft) or Pilot (small craft)", 0),
        ("Survival", 0), ("Mechanic", 0), ("Astrogation", 0), ("Comms", 0),
        ("Gun Combat", 0), ("Comms", 0), ("Pilot (spacecraft)", 0),
        ("Pilot (small craft)", 0), ("Life Science", 0), ("Stealth", 0), ("Recon", 0),
        ("Medic", 0), ("Navigation", 0), ("Engineer", 0), ("Computers", 0),
        ("Space Science", 0), ("Jack of all Trades", 0)),
    ("Explorer", "Survey"): (("Pilot", 0), ("Survival", 0), ("Mechanic", 0),
        ("Astrogation", 0), ("Comms", 0), ("Gun Combat", 0), ("Str", 1),
        ("Dex", 1), ("End", 1), ("Int", 1), ("Edu", 1),
        ("Jack of all Trades", 0), ("Pilot (spacecraft) or Pilot (small craft)", 0),
        ("Survival", 0), ("Mechanic", 0), ("Astrogation", 0), ("Comms", 0),
        ("Gun Combat", 0), ("Sensors", 0), ("Persuade", 0), ("Pilot (small craft)", 0),
        ("Navigation", 0), ("Diplomat", 0), ("Streetwise", 0), ("Medic", 0),
        ("Navigation", 0), ("Engineer", 0), ("Computers", 0), ("Space Science", 0),
        ("Jack of all Trades", 0)),
    ("Explorer", "Exploration"): (("Pilot", 0), ("Survival", 0), ("Mechanic", 0),
        ("Astrogation", 0), ("Comms", 0), ("Gun Combat", 0), ("Str", 1),
        ("Dex", 1), ("End", 1), ("Int", 1), ("Edu", 1),
        ("Jack of all Trades", 0), ("Pilot (spacecraft) or Pilot (small craft)", 0),
        ("Survival", 0), ("Mechanic", 0), ("Astrogation", 0), ("Comms", 0),
        ("Gun Combat", 0), ("Comms", 0), ("Pilot (spacecraft)", 0),
        ("Pilot (small craft)", 0), ("Life Science", 0), ("Stealth", 0), ("Recon", 0),
        ("Medic", 0), ("Navigation", 0), ("Engineer", 0), ("Computers", 0),
        ("Space Science", 0), ("Jack of all Trades", 0)),
    ("Psion", "Wild Talent"): (("Telepathy", 0), ("Clairvoyance", 0),
        ("Telekinesis", 0), ("Awareness", 0), ("Teleportation", 0),
        ("Any Skill", 0), ("Edu", 1), ("Int", 1), ("Str", 1),
        ("Dex", 1), ("End", 1), ("Psi", 1), ("Telepathy", 0),
        ("Clairvoyance", 0), ("Telekinesis", 0), ("Awareness", 0),
        ("Teleportation", 0), ("Any Skill", 0), ("Telepathy", 0),
        ("Telekinesis", 0), ("Deception", 0), ("Stealth", 0), ("Streetwise", 0),
        ("Melee or Gun Combat", 0), ("Comms", 0), ("Computers", 0), ("Language", 0),
        ("Medic", 0), ("Life Science", 0), ("Space Science", 0)),
    ("Psion", "Adept"): (("Telepathy", 0), ("Clairvoyance", 0), ("Telekinesis", 0),
        ("Awareness", 0), ("Teleportation", 0), ("Any Skill", 0), ("Edu", 1),
        ("Int", 1), ("Str", 1), ("Dex", 1), ("End", 1),
        ("Psi", 1), ("Telepathy", 0), ("Clairvoyance", 0), ("Telekinesis", 0),
        ("Awareness", 0), ("Teleportation", 0), ("Any Skill", 0), ("Telepathy", 0),
        ("Clairvoyance", 0), ("Awareness", 0), ("Medic", 0), ("Persuade", 0),
        ("Social Science", 0), ("Comms", 0), ("Computers", 0), ("Language", 0),
        ("Medic", 0), ("Life Science", 0), ("Space Science", 0)),
    ("Psion", "Psi-Warrior"): (("Telepathy", 0), ("Clairvoyance", 0),
        ("Telekinesis", 0), ("Awareness", 0), ("Teleportation", 0),
        ("Any Skill", 0), ("Edu", 1), ("Int", 1), ("Str", 1),
        ("Dex", 1), ("End", 1), ("Psi", 1), ("Telepathy", 0),
        ("Clairvoyance", 0), ("Telekinesis", 0), ("Awareness", 0),
        ("Teleportation", 0), ("Any Skill", 0), ("Telepathy", 0), ("Awareness", 0),
        ("Teleportation", 0), ("Gun Combat", 0), ("Battle Dress", 0), ("Recon", 0),
        ("Comms", 0), ("Computers", 0), ("Language", 0), ("Medic", 0),
        ("Life Science", 0), ("Space Science", 0)),
}

RANKS = {
    ("Warden", "Enforcer"):
        (None, ("Occult", 1), None, ("Investigate", 1), None, ("Leadership", 1), ("Soc", 1)),
    ("Warden", "Investigator"):
        (None, ("Occult", 1), None, ("Investigate", 1), None, ("Leadership", 1), ("Soc", 1)),
    ("Warden", "Researcher"):
        (None, ("Occult", 1), None, ("Investigate", 1), None, ("Leadership", 1), ("Soc", 1)),
    ("Agent", "Law Enforcement"):
        (None, ("Streetwise", 1), None, None, ("Investigate", 1), ("Admin", 1), ("Soc", 1)),
    ("Agent", "Intelligence"):
        (None, ("Deception", 1), ("Investigate", 1), None, ("Gun Combat", 1), None, None),
    ("Agent", "Corporate"):
        (None, ("Deception", 1), ("Investigate", 1), None, ("Gun Combat", 1), None, None),
    ("Army", "Support"):
        (("Gun Combat (rifle)", 1), ("Recon", 1), None, ("Leadership", 1), None, None, None),
    ("Army", "Infantry"):
        (("Gun Combat (rifle)", 1), ("Recon", 1), None, ("Leadership", 1), None, None, None),
    ("Army", "Cavalry"):
        (("Gun Combat (rifle)", 1), ("Recon", 1), None, ("Leadership", 1), None, None, None),
    ("Citizen", "Corporate"):
        (None, None, ("Admin", 1), None, ("Advocate", 1), None, ("Soc", 1)),
    ("Citizen", "Worker"):
        (None, None, ("Trade", 1), None, ("Mechanic", 1), None, ("Engineer", 1)),
    ("Citizen", "Colonist"):
        (None, None, ("Survival", 1), None, ("Navigation", 1), None, ("Gun Combat", 1)),
    ("Drifter", "Barbarian"):
        (None, ("Survival", 1), ("Melee (blade)", 1), None, ("Leadership", 1), None, None),
    ("Drifter", "Wanderer"):
        (None, ("Streetwise", 1), None, ("Deception", 1), None, None, None),
    ("Drifter", "Scavenger"):
        (None, ("Vacc Suit", 1), None, ("Trade (belter) or Mechanic)", 1), None, None, None),
    ("Entertainer", "Artist"):
        (None, ("Art", 0), None, ("Investigate", 0), None, ("Soc", 1), None),
    ("Entertainer", "Journalist"):
        (None, ("Comms", 0), ("Investigate", 0), None, ("Persuade", 0), None, ("Soc", 1)),
    ("Entertainer", "Performer"):
        (None, ("Dex", 1), None, ("Str", 1), None, ("Soc", 1), None),
    ("Marines", "Support"):
        (("Melee (blade) or Gun Combat", 1), ("Gun Combat", 1), None, ("Leadership", 1), None, ("End", 1), None),
    ("Marines", "Star Marines"):
        (("Melee (blade) or Gun Combat", 1), ("Gun Combat", 1), None, ("Leadership", 1), None, ("End", 1), None),
    ("Marines", "Ground Assault"):
        (("Melee (blade) or Gun Combat", 1), ("Gun Combat", 1), None, ("Leadership", 1), None, ("End", 1), None),
    ("Merchant", "Merchant Marine"):
        (None, ("Mechanic", 1), None, None, ("Pilot", 1), ("Soc", 1), None),
    ("Merchant", "Free Trader"):
        (None, ("Persuade", 1), None, ("Jack of all Trades", 1), None, None, None),
    ("Merchant", "Broker"):
        (None, ("Broker", 1), None, ("Streetwise", 1), None, None, None),
    ("Navy", "Line/Crew"):
        (None, ("Mechanic", 1), ("Vacc Suit", 1), None, ("End", 1), None, None),
    ("Navy", "Engineering/Gunnery"):
        (None, ("Mechanic", 1), ("Vacc Suit", 1), None, ("End", 1), None, None),
    ("Navy", "Flight"):
        (None, ("Mechanic", 1), ("Vacc Suit", 1), None, ("End", 1), None, None),
    ("Aristocrat", "Administrator"):
        (None, ("Admin", 1), None, ("Advocate", 1), None, ("Leadership", 1), None),
    ("Aristocrat", "Diplomat"):
        (None, ("Admin", 1), None, ("Advocate", 1), None, ("Diplomat", 1), None),
    ("Aristocrat", "Dilettante"):
        (None, ("Carouse", 1), None, ("Persuade", 1), None, ("Jack of all Trades", 1), None),
    ("Nobility", "Administrator"):
        (None, ("Admin", 1), None, ("Advocate", 1), None, ("Leadership", 1), None),
    ("Nobility", "Diplomat"):
        (None, ("Admin", 1), None, ("Advocate", 1), None, ("Diplomat", 1), None),
    ("Nobility", "Dilettante"):
        (None, ("Carouse", 1), None, ("Persuade", 1), None, ("Jack of all Trades", 1), None),
    ("Rogue", "Thief"):
        (None, ("Stealth", 1), None, ("Streetwise", 1), None, ("Recon", 1), None),
    ("Rogue", "Enforcer"):
        (None, ("Persuade", 1), None, ("Melee or Gun Combat", 1), None, ("Streetwise", 1), None),
    ("Rogue", "Pirate"):
        (None, ("Pilot or Gunner", 1), None, ("Melee or Gun Combat", 1), None, ("Engineer or Navigation", 1), None),
    ("Scholar", "Field Researcher"):
        (None, ("Social Science", 1), None, ("Investigate", 1), None, ("Computers", 1), None),
    ("Scholar", "Scientist"):
        (None, ("Physical Science", 1), None, ("Investigate", 1), None, ("Computers", 1), None),
    ("Scholar", "Physician"):
        (None, ("Medic", 1), None, ("Life Science", 1), None, ("Social Science", 1), None),
    ("Scholar", "Occultist"):
        (None, ("Occult", 1), None, ("Investigate", 1), None, ("Computers", 1), None),
    ("Scout", "Courier"):
        (None, ("Vacc Suit", 1), None, ("Pilot", 1), None, None, None),
    ("Scout", "Survey"):
        (None, ("Vacc Suit", 1), None, ("Pilot", 1), None, None, None),
    ("Scout", "Exploration"):
        (None, ("Vacc Suit", 1), None, ("Pilot", 1), None, None, None),
    ("Explorer", "Survey"):
        (None, ("Vacc Suit", 1), None, ("Pilot", 1), None, None, None),
    ("Explorer", "Exploration"):
        (None, ("Vacc Suit", 1), None, ("Pilot", 1), None, None, None),
    ("Psion", "Wild Talent"):
        (None, ("Survival or Streetwise", 1), None, ("Deception", 1), None, None, None),
    ("Psion", "Adept"):
        (None, ("Science (psionology)", 1), None, ("Psi", 1), None, None, ("Psi", 1)),
    ("Psion", "Psi-Warrior"):
        (None, ("Gun Combat", 1), ("Leadership", 1), None, None, ("Tactics", 1), None),
    ("Army Officer", "Support"):
        (None, ("Leadership", 1), None, ("Tactics (military)", 1), None, None, ("Soc", 1)),
    ("Army Officer", "Infantry"):
        (None, ("Leadership", 1), None, ("Tactics (military)", 1), None, None, ("Soc", 1)),
    ("Army Officer", "Cavalry"):
        (None, ("Leadership", 1), None, ("Tactics (military)", 1), None, None, ("Soc", 1)),
    ("Marines Officer", "Support"):
        (None, ("Leadership", 1), None, ("Tactics", 1), None, ("Soc", 1), None),
    ("Marines Officer", "Star Marines"):
        (None, ("Leadership", 1), None, ("Tactics", 1), None, ("Soc", 1), None),
    ("Marines Officer", "Ground Assault"):
        (None, ("Leadership", 1), None, ("Tactics", 1), None, ("Soc", 1), None),
    ("Navy Officer", "Line/Crew"):
        (None, ("Melee (blade)", 1), ("Leadership", 1), None, ("Tactics (naval)", 1), ("Soc", 1), ("Soc", 1)),
    ("Navy Officer", "Engineering/Gunnery"):
        (None, ("Melee (blade)", 1), ("Leadership", 1), None, ("Tactics (naval)", 1), ("Soc", 1), ("Soc", 1)),
    ("Navy Officer", "Flight"):
        (None, ("Melee (blade)", 2), ("Leadership", 1), None, ("Tactics (naval)", 1), ("Soc", 1), ("Soc", 1)),
}

BENEFITS = {
    "Agent": (("Scientific Equipment", None),
              ("Int", 1),
              ("Ship Shares", 1),
              ("Weapon", None),
              ("Combat Implant", None),
              (("Soc", 1), ("Combat Implant", None)),
              ("TAS Membership", None)),
    "Army": (("Combat Implant", None),
             ("Int", 1),
             ("Edu", 1),
             ("Weapon", None),
             ("Armor", None),
             (("End", 1), ("Combat Implant", None)),
             ("Soc", 1)),
    "Citizen": (("Ship Shares", 1),
                ("Ally", None),
                ("Int", 1),
                ("Gun", None),
                ("Edu", 1),
                ("Ship Shares", 2),
                ("TAS Membership", None)),
    "Drifter": (("Contact", None),
                ("Weapon", None),
                ("Ally", None),
                ("Weapon", None),
                ("Edu", 1),
                ("Ship Shares", 1),
                ("Ship Shares", 2)),
    "Entertainer": (("Contact", None),
                    ("Soc", 1),
                    ("Contact", None),
                    ("Soc", 1),
                    ("Int", 1),
                    ("Ship Shares", 2),
                    ("Soc and Edu", 1)),
    "Marines": (("Armor", None),
                ("Int", 1),
                ("Edu", 1),
                ("Weapon", None),
                ("TAS Membership", None),
                (("Armor", None), ("End", 1)),
                ("Soc", 2)),
    "Merchant": (("Blade", None),
                 ("Int", 1),
                 ("Edu", 1),
                 ("Gun", None),
                 ("Ship Shares", 1),
                 ("Free Trader", None),
                 ("Free Trader", None)),
    "Navy": ((("Air/Raft", None), ("Ship Shares", 1)),
             ("Int", 1),
             (("Edu", 1), ("Ship Shares", 2)),
             ("Weapon", None),
             ("TAS Membership", None),
             (("Ship's Boat", None), ("Ship Shares", 2)),
             ("Soc", 2)),
    "Nobility": (("Ship Shares", 1),
                 ("Ship Shares", 2),
                 ("Blade", None),
                 ("Soc", 1),
                 ("TAS Membership", None),
                 ("Yacht", None),
                 (("Soc", 1), ("Yacht", None))),
    "Aristocrat": (("Ship Shares", 1),
                   ("Ship Shares", 2),
                   ("Blade", None),
                   ("Soc", 1),
                   ("TAS Membership", None),
                   ("Yacht", None),
                   (("Soc", 1), ("Yacht", None))),
    "Rogue": (("Ship Shares", 1),
              ("Weapon", None),
              ("Int", 1),
              ("Ship Shares", 2),
              ("Armor", None),
              ("Dex", 1),
              ("Corsair", None)),
    "Scholar": (("Int", 1),
                ("Edu", 1),
                ("Ship Shares", 2),
                ("Soc", 1),
                ("Scientific Equipment", None),
                ("Lab Ship", None),
                ("Lab Ship", None)),
    "Scout": (("Ship Shares", 1),
              ("Int", 1),
              ("Edu", 1),
              ("Weapon", None),
              ("Weapon", None),
              ("Scout Ship", None),
              ("Scout Ship", None)),
    "Explorer": (("", None),
                 ("", None),
                 ("", None),
                 ("", None),
                 ("", None),
                 ("", None),
                 ("", None)),
    "Psion": (("Gun", None),
              ("Ship Shares", 2),
              ("Contact", None),
              ("TAS Membership", None),
              ("Contact", None),
              ("Combat Implant", None),
              ("Ship Shares", 10)),
    "Warden": (("", None),
               ("", None),
               ("", None),
               ("", None),
               ("", None),
               ("", None),
               ("", None)),
    }

CREDITS = {
    "Agent": (1000, 2000, 5000, 7500, 10000, 25000, 50000),
    "Army": (2000, 5000, 10000, 10000, 10000, 20000, 50000),
    "Citizen": (1000, 5000, 10000, 10000, 10000, 50000, 100000),
    "Drifter": (0, 0, 1000, 2000, 3000, 4000, 8000),
    "Entertainer": (0, 0, 10000, 10000, 40000, 40000, 80000),
    "Marines": (2000, 5000, 5000, 10000, 20000, 30000, 40000),
    "Merchant": (1000, 5000, 10000, 20000, 20000, 40000, 40000),
    "Navy": (1000, 5000, 5000, 10000, 20000, 50000, 50000),
    "Nobility": (10000, 10000, 50000, 50000, 100000, 100000, 200000),
    "Aristocrat": (10000, 10000, 50000, 50000, 100000, 100000, 200000),
    "Rogue": (0, 0, 10000, 10000, 50000, 100000, 100000),
    "Scholar": (5000, 10000, 20000, 30000, 40000, 60000, 100000),
    "Scout": (20000, 20000, 30000, 30000, 50000, 50000, 50000),
    "Explorer": (20000, 20000, 30000, 30000, 50000, 50000, 50000),
    "Psion": (1000, 2000, 4000, 4000, 8000, 8000, 16000),
    "Warden": (1000, 2000, 5000, 7500, 10000, 25000, 50000),
}

AGING = (
    # inverted
    (1, 0, 0, 0),
    (1, 1, 0, 0),
    (1, 1, 1, 0),
    (2, 1, 1, 0),
    (2, 2, 1, 0),
    (2, 2, 2, 0),
    (2, 2, 2, 1),
)

PERSONALITIES = (
    ('Pessimistic', 'Courage', 'Generous', 'Argumentative', 'Careless',
     'Suspicious', 'Quiet', 'Greedy', 'Opinionated', 'Violent',
     'Uncivilized', 'Capricious', 'Optimistic', 'Exacting', 'Sober',
     'Curious', 'Naive', 'Friendly', 'Arrogant', 'Moody'),
    ('Thoughtless', 'Narrow-minded', 'Retiring', 'Nervous', 'Hot-tempered',
     'Realistic', 'Irreverent', 'Happy', 'No common sense', 'Covetous',
     'Forgiving', 'Overbearing', 'Shy', 'Compassionate', 'Charitable',
     'Cruel', 'Perfectionist', 'Prying', 'Sadistic', 'Spendthrift',
     'Mousy', 'Brave', 'Keen', 'Intellectual', 'Cheerful',
     'Garrulous', 'Boorish', 'Harsh', 'Paranoid', 'Kind-hearted',
     'Mischievous', 'Thrifty', 'Lusty', 'Uncultured', 'Punctual',
     'Depressing', 'Miserly', 'Gloomy', 'Absent-minded', 'Jealous',
     'Dull', 'Blustering', 'Foolhardy', 'Kind', 'Diplomatic',
     'Proud', 'Graceless', 'Scheming', 'Barbaric', 'Practical',
     'Morose', 'Rude', 'Trusting', 'Soft-spoken', 'o',
     'Antagonistic', 'Inquisitive', 'Bigoted', 'Secretive', 'Hick',
     'Reverent', 'Haughty', 'Extravagant', 'Truthful', 'Pleasant',
     'Biased', 'Insensitive', 'Level-headed', 'Fearless', 'Sarcastic',
     'Driven', 'Warlike', 'Laconic', 'Compulsive', 'Craven',
     'Honest', 'Madcap', 'Avaricious', 'Cynical', 'Articulate',
     'Perceptive', 'Elitist', 'Aloof', 'Obsequious', 'Cautious',
     'Innocent', 'Crude', 'Immoral', 'Easy-going', 'Ponderous',
     'Impulsive', 'Hard-hearted', 'Dreamy', 'Hide-bound', 'Stern',
     'Fatalistic', 'Gullible', 'Vengeful', 'Wastrel', 'Irritable'),
    ('Multiple personalities', 'Never throws anything away', 'Narrow-minded', 'Speaks in metaphor', 'Nervous',
     "Gets peoples' names wrong", 'Blinks a lot', 'Has impressive hand', 'Ponderous', 'Runs everywhere',
     'Very short', 'Irreverent', 'Very tall', 'Famous', 'Covetous',
     'Speaks with heavy accent', 'Picks nose', 'Has a tattoo of a grey bird on chest', 'Has an artificial backside', 'Prefers the company of another race',
     'Dull senses', 'Only deals with local people', 'Avoids eye contact', 'Has an artificial calf', 'Obsessively Craven',
     'Plays with hair', 'Very thin', 'Was formerly much richer', 'Dresses wrong for the weather', 'Overbearing',
     'Eats raw meat', 'Compassionate', 'Has a secret fantasy : Spells, baneful', 'Keen',
     'Perfectionist', 'Tells jokes', 'Sadistic', 'Spendthrift', 'Mousy',
     'Exaggerates everything', 'Brave', 'Morose', 'Suffers from a long term illness', 'Very agile',
     'Seems very intelligent', 'Intellectual', 'Cheerful', 'Garrulous', 'Extravagant',
     'Nocturnal', 'Accompanied by Madcap daughter', 'Admires a historical hero', 'Collects lanterns', 'Heavily tattooed',
     'Very fat', 'Paranoid', 'Hair dyed yellow', 'Kind-hearted', 'Mischievous',
     'Thrifty', 'Slobbish', 'Never uses contractions', 'Lusty', 'Teetotal',
     'Uncultured', 'Whittles wood in spare time', 'Keeps hand on weapon', 'Punctual', 'Has startlingly grey hair',
     'Mixes words up', 'Depressing', 'Owns slaves', 'Miserly', 'Coughs a lot',
     'Jealous', 'Dull', 'Has a prominent scar on shin', 'Blustering', 'Foolhardy',
     'Kind', 'Foul smelling', 'Has a phobia of boots', 'Diplomatic', 'Wears a flower in buttonhole or hair',
     'Proud', 'Flatulant', 'Barbaric', 'Wears clothes a size too small', 'Has impressive scalp',
     'Has warts', 'Alcoholic', 'Practical', 'Has a prominent scar on back', 'Obsequious',
     'Has a secret fantasy : Espionage ', 'Recently lost daughter in a tragedy', 'Trusting', 'Has an identical twin',
     'Whispers constantly to self', 'Has wanderlust', 'Antagonistic', 'Inquisitive', 'Bigoted',
     'Talks to inanimate objects', 'Accompanied by Avaricious lover', 'Pale',
     'Reverent', 'Very deep bass voice', 'Haughty', 'Deceitful', 'Boorish', 'Uses foul language',
     'Talks very fast', 'Prudish', 'Cracks knuckles', 'Addicted to a healing herb', 'Truthful',
     'Always accompanied by Soft-spoken lover', 'Driven', 'Biased', 'Was formerly much poorer', 'Gloomy',
     'Rude', 'Constantly turns head as if listening to things', 'Sarcastic', 'Pleasant', 'Close to family',
     'Always scratching', 'Stomps on bugs', 'Warlike', 'Keeps looking over shoulder', 'Talks to animals',
     'Laconic', 'Vegetarian', 'Compulsive', 'Owns a signature item - a distinctive spectacles', 'Craven',
     'Honest', 'Madcap', 'Avaricious', 'Inspires loyalty in others', 'Dances badly',
     'Has many missing teeth', 'Licks lips', 'Slurred speech', 'Physically weak', 'Tanned',
     'Forgiving', 'Beautiful', 'Cynical', 'Older than appears', 'Well known for being skilled at a trade',
     'Foams at the mouth when excited', 'Articulate', 'Perceptive', 'Searching for a long-lost aunt', 'Elitist',
     'Aloof', 'Has a secret fantasy : Cannibalism', 'Repeats self in coversations', 'Very wise', 'Has recently fallen in love',
     'Hair dyed pink', 'Sports enthusiast', 'Frowns all the time', 'Gives people inappropriate nicknames', 'Accompanied by Compulsive grandfather',
     'Only deals with people of same religion', 'Bites nails (or claws)', 'Virgin', 'Innocent', 'Crude',
     'Acts like a character in a Mystery', 'Enjoys watching combat sports', 'Has a prominent scar on eye', 'Uses hands to emphasis speech', 'Suffers from hallucinations',
     'Hypochondriac', 'Whispers when speaking', 'Hot-tempered', 'Impulsive', 'Loves stories',
     'Constantly checking own appearance in mirrors, ponds etc', 'Hard-hearted', 'Dreamy', 'Hide-bound',
     'On the run from criminals', 'Searching for lost map', 'Easy-going', 'Hair dyed silver', 'Irritable',
     'Known by a nickname', 'Sweet tooth', 'Hugs trees', 'Gullible', 'Ugly',
     'Speaks in poetry', 'Searching for lost dagger', 'Very hairy', 'Younger than appears', 'Vengeful',
     'Flirt', 'Realistic', 'Smiles all the time', 'Always chewing', 'Only deals with people of same race',
     'Stern', 'Has visions', 'On the run from the law', 'Once owned slaves'))


from __future__ import annotations

import shelve
import string, random

from datetime import datetime
from .. import DB_REVIEW_LOCATION

class Review():
  def __init__(
    self,
    review_uid: str,
    from_uid: str,
    to_uid:str,
    rating: float,
    comments: str,
    created_at: str
  ):
    self.review_uid = review_uid
    self.from_uid = from_uid
    self.to_uid = to_uid
    self.rating = rating
    self.comments = comments
    self.created_at = created_at

  @staticmethod
  def create_review(
    from_uid: str,
    to_uid: str,
    rating: float,
    comments:str,
    created_at: str
  ):
    review_uid  =  ''.join(random.sample(string.ascii_uppercase, 5))

    review = Review(
    review_uid,
    from_uid,
    to_uid,
    rating,
    comments,
    created_at
    )

    with shelve.open(DB_REVIEW_LOCATION) as db:
      db[review_uid] = review
      db.sync()

    return review


#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Created with YooLiang Technology (侑良科技).
# Author: Qi-Liang Wen (温啓良）
# Web: http://www.yooliang.com/
# Date: 2016/1/28.
import re

from argeweb.core.ndb import decode_key
from datetime import datetime

class ParamInfo(object):
    def __init__(self, controller):
        """ easy way to get param from request

        Args:
            key: the key to get from request
            default_value: then value not exits return
        """
        self.request = controller.request

    def string_is_empty(self, key=''):
        key = key.strip()
        if key is None or key is '' or key is u'':
            return True
        else:
            return False

    def has(self, key):
        return key in self.request.params

    def get_ndb_record(self, key='', default_value=None):
        """ get from request and try to parse to a int

        Args:
            key: the key to get from request
            default_value: then value not exits return
        """
        if key is '':
            target = default_value
        else:
            if key in self.request.params:
                target = self.request.get(key)
            else:
                target = key
        try:
            if target is not None:
                return decode_key(target).get()
        except:
            return None

    def get_integer(self, key='', default_value=0):
        """ get from request and try to parse to a int

        Args:
            key: the key to get from request
            default_value: then value not exits return
        """
        if key is '':
            return default_value
        try:
            if key not in self.request.params:
                return default_value
            _a = self.request.get(key) if int(self.request.get(key)) is not None else u''
            return default_value if _a == '' else int(_a)
        except:
            return default_value

    def get_float(self, key='', default_value=0.0):
        """ get from request and try to parse to a float

        Args:
            key: the key to get from request
            default_value: then value not exits return
        """
        if key is '':
            return default_value
        try:
            if key not in self.request.params:
                return default_value
            _a = self.request.get(key) if float(self.request.get(key)) is not None else u''
            if _a == '' or _a == u'':
                _a = default_value
            return default_value if _a == '' else float(_a)
        except:
            return default_value

    def get_string(self, key='', default_value=u''):
        """ get from request and try to parse to a str(unicode)

        Args:
            key: the key to get from request
            default_value: then value not exits return
        """
        if key is '':
            return default_value
        try:
            if key not in self.request.params:
                rv = default_value
            else:
                rv = self.request.get(key)
        except:
            rv = default_value
        if rv is None or rv is '' or rv is u'':
            rv = u''
        return rv

    def get_datetime(self, key='', default_value=None):
        str_format = self.get_string(key+'-format', '%Y-%m-%dT%H:%M:%S')
        str_date = self.get_string(key, u'')
        if str_date is u'':
            if default_value is None:
                return datetime.today()
            return default_value
        else:
            try:
                return datetime.strptime(str_date, str_format)
            except (TypeError, ValueError):
                try:
                    return datetime.strptime(str_date, '%Y-%m-%dT%H:%M')
                except (TypeError, ValueError):
                    return datetime.strptime(str_date, '%Y-%m-%d')

    def get_email(self, key='', default_value=None):
        email = self.get_string(key).strip()
        if len(email) > 7:
            if re.match('^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$', email) is not None:
                return email
        return default_value

    def get_header(self, key='', default_value=u''):
        """ get from request and try to parse to a str(unicode)

        Args:
            key: the key to get from request
            default_value: then value not exits return
        """
        from inflector import titleize
        key = '-'.join(titleize(key).split(' '))
        if key is '':
            return default_value
        try:
            if key not in self.request.headers.keys():
                rv = default_value
            else:
                rv = self.request.headers.get(key)
        except:
            rv = default_value
        if rv is None or rv is '' or rv is u'':
            rv = u''
        return rv

    def get_boolean(self, key='', default_value=False):
        """ get from request and try to parse to a bool

        Args:
            key: the key to get from request
            default_value: then value not exits return
        """
        if key is '':
            return default_value
        try:
            if key not in self.request.params:
                return default_value
            else:
                v = self.request.get(key)
                if v.lower() == u'false':
                    return False
                if v.lower() == u'0':
                    return False
                return bool(v)
        except:
            return default_value

    def get_list(self, key='', exactly_equal=True, use_dict=False):
        """ get from request and try to parse to a list
        Args:
            key: the key to get from request
            exactly_equal: item must equal key
            use_dict: if True return key value dict object
        """
        return_list = []
        if key is not '':
            for item in self.request.POST.multi._items:
                if exactly_equal:
                    if item[0] == key:
                        if use_dict:
                            return_list.append({'key': str(item[0]), 'value': str(item[1])})
                        else:
                            return_list.append(item[1])
                else:
                    if item[0].find(key) >= 0:
                        if use_dict:
                            return_list.append({'key': str(item[0]), 'value': str(item[1])})
                        else:
                            return_list.append(item[1])
        return return_list

    def get_json(self, key=''):
        try:
            import simplejson as json
        except ImportError:
            import json

        if key is '':
            return {}
        data = self.request.get(key)
        return json.loads(data)

    def get_search(self):
        """ get from request and try to parse to a list

        Args:
            key: the key to get from request
            default_value: then value not exits return
        """
        search_str = []
        for i in xrange(10):
            if self.request.get('search[%s][type]' % i) == 'text' and self.request.get('search[%s][value]' % i) != '':
                search_str.append({
                    'value': u'' + self.request.get('search[%s][value]' % i).replace(u'\'', u'\'\''),
                    'field': u'' + self.request.get('search[%s][field]' % i),
                    'type': u'' + self.request.get('search[%s][type]' % i),
                    'operator': u'' + self.request.get('search[%s][operator]' % i),
                })
        return search_str

    def get_mobile_number(self, key='', default_value=u'', taiwan_format=True):
        """ get from request and try to parse to a str(unicode)

        Args:
            key: the key to get from request
            default_value: then value not exits return
        """
        if key is '':
            return default_value
        try:
            if key not in self.request.params:
                rv = default_value
            else:
                rv = self.request.get(key)
        except:
            rv = default_value
        if rv is '' or rv is u'':
            return None
        else:
            if len(rv) != 10 or rv.startswith('09') is False:
                return None
        if taiwan_format:
            rv = "+886" + rv[1:]
        return rv

    def get_base64(self, key='', default_value=None):
        """ get from request and try to parse to a str(unicode)

        Args:
            key: the key to get from request
            default_value: then value not exits return
        """
        import base64
        if key is '':
            return default_value
        try:
            if key not in self.request.params:
                rv = default_value
            else:
                rv = self.request.get(key)
        except:
            rv = default_value
        if rv is None or rv is '' or rv is u'':
            return None
        return base64.urlsafe_b64decode(str(rv))


#!/usr/bin/env python
###################################

from argparse import ArgumentParser
import sys, urllib2, csv

def write(cogs, infile, outfile):
    if outfile: hout = open(outfile, 'w')
    else: hout = sys.stdout
    hin = open(infile, 'r')
    hincsv = csv.reader(hin, delimiter = '\t')
    houtcsv = csv.writer(hout, delimiter = '\t')
    for i,row in enumerate(hincsv):
        if i==0:
            header= row[1:]
            out = ["Cat1","Cat2","COG"]+header
            houtcsv.writerow(out)
            continue
        cog = row[0]
        try: out = [cogs[cog]["firstcat"],cogs[cog]["secondcat"],cog+" "+cogs[cog]["name"]]+row[1:]
        except KeyError: out = [cog,cog,cog]+row[1:]
        houtcsv.writerow(out)
    hout.close()
    hin.close()

def main():
    parser = ArgumentParser()
    parser.add_argument("-i", "--infile", type=str,
            help="COG table for which to add hierarchy")
    #parser.add_argument("-H", "--hier", type=str,
    #        help="Supply a COG functional hierarchy flatfile. If none is supplied the script attempts to download one from ftp://ftp.ncbi.nih.gov/pub/COG/COG/fun.txt")
    parser.add_argument("-o", "--outfile", type=str,
            help="Write tab-delimited pathway hierarchy to outfile. Defaults to stdout")
    args = parser.parse_args()

    if not args.infile: sys.exit(parser.print_help())

    cogs = ParseWHOG()
    cogs = ParseFUN(cogs)
    write(cogs, args.infile, args.outfile)

def ParseWHOG():
    cogs = {}
    whogurl = "ftp://ftp.ncbi.nih.gov/pub/COG/COG/whog"
    data = urllib2.urlopen(whogurl)
    data = data.read()
    data = data.split("\n")
    for line in data:
        if line=="": continue
        if not line[0]=="[": continue
        items = line.rsplit()
        cats = items[0]
        cog = items[1]
        name = " ".join(items[2:])
        cats = cats.replace("[","")
        cats = cats.replace("]","")
        cogs[cog] = {"name": name, "catletter": cats[0], "firstcat": "", "secondcat": ""}
    return cogs

def ParseFUN(cogs):
    f = urllib2.urlopen("ftp://ftp.ncbi.nih.gov/pub/COG/COG/fun.txt")
    data = f.read()
    data = data.split("\n")
    cats = {}
    for line in data:
        line = line.lstrip()
        if line=="": continue
        if line[0]=="[":
            catletter = line[1]
            name = line.split("]")[1].lstrip()
            name = name.rstrip()
            cats[catletter] = {"secondcat": name, "firstcat":parent}
        else: parent = line
    for cog in cogs.keys():
        catletter = cogs[cog]["catletter"]
        firstcat = cats[catletter]["firstcat"]
        secondcat = cats[catletter]["secondcat"]
        cogs[cog]["firstcat"] = firstcat
        cogs[cog]["secondcat"] = secondcat
    return cogs

if __name__ == '__main__':
    main()


import os
from enum import Enum, auto
from typing import Dict, Tuple, List
import time
import subprocess
import platform
from tkinter import *
from tkinter import ttk
from tkinter.filedialog import askopenfilename
import numpy as np
import tensorflow as tf
from PIL import Image, ImageTk
from egg_classifier.image_processor import ImageSplitter, ImageDrawer
from egg_classifier.classifier import Classifier
from egg_classifier.classifier.mobilenetv2_classifier import Mobilenetv2Classifier
from egg_classifier.classifier.histogram_classifier import HistogramClassifier

tf.autograph.set_verbosity(0)

class ClassifierType(Enum):
    MOBILENETV2 = auto()
    HISTOGRAM = auto()

class EggClassifier():
    def __init__(self, number_of_rows: int, number_of_columns: int,
                 offset_x_percent: int, offset_y_percent: int,
                 radius: int, colors: Dict[str, str], font: str,
                 font_size: int, classifier_type: ClassifierType, model_path: str,
                 classes: List[str], prediction_threshold: float,
                 image_size: Tuple[int, int] = (128, 128)) -> None:
        assert len(classes) == 2
        assert prediction_threshold >= 0 and prediction_threshold <= 1
        assert len(colors) == 2

        self.__image_splitter: ImageSplitter = ImageSplitter(number_of_rows, number_of_columns,
                                                             offset_x_percent, offset_y_percent)
        self.__image_drawer: ImageDrawer = ImageDrawer(number_of_rows, number_of_columns, radius,
                                                       colors, font, font_size)
        self.__classes = classes
        self.__prediction_threshold = prediction_threshold
        self.__classifier: Classifier = None
        if classifier_type == ClassifierType.MOBILENETV2:
            self.__classifier = Mobilenetv2Classifier(model_path, image_size)
        else:
            self.__classifier = HistogramClassifier(model_path, image_size)

    def predict(self, image_np: np.ndarray) -> np.ndarray:
        images = self.__image_splitter.split_image(image_np)
        outputs = self.__classifier.predict(images)
        labels = [self.__classes[0] if x <=
                  self.__prediction_threshold else self.__classes[1] for x in outputs]
        output_image = self.__image_drawer.draw(image_np, labels)
        return output_image

class EggClassifierUI():
    def __init__(self, classifier: EggClassifier, image_size: Tuple[int, int]):
        self.__classifier = classifier
        self.__image_size = image_size
        self.__image_tk = None
        self.__delete_images()
        self.__initialize()

    def __initialize(self):
        self.__root = Tk()
        self.__root.title("Egg Classifier")
        self.__root.resizable(False, False)
        self.__master = ttk.Frame(self.__root)
        self.__master.grid(row=0, column=0, padx=8, pady=4)
        file_button = ttk.Button(
            self.__master,
            text="Browse",
            command=self.__load_file
        )
        file_button.grid(row=1, column=0, sticky=(N, W, E, S))

        capture_button = ttk.Button(
            self.__master,
            text="Capture",
            command=self.__capture
        )
        capture_button.grid(row=1, column=1, sticky=(N, W, E, S))

        self.__canvas = Canvas(
            self.__master, width=self.__image_size[0], height=self.__image_size[1])
        self.__canvas.grid(row=0, column=0, columnspan=2, sticky=(N, W, E, S))

    def __load_file(self) -> None:
        file_name = askopenfilename(
            filetypes=[("Image", "*.jpg;*.jpeg;*.png")])
        start_time = time.time()
        self.__predict(file_name)
        end_time = time.time()
        execution_time = end_time - start_time
        print(f"Execution Time: {execution_time} seconds")

    def __capture(self) -> None:
        if platform.system() == "Windows":
            return
        subprocess.run([
            "nvgstcapture-1.0",
            "--automate",
            "--capture-auto"
        ])
        image_path = self.__get_image_path()
        if image_path is None:
            print("no captured image found")
            return
        start_time = time.time()
        self.__predict(image_path)
        end_time = time.time()
        execution_time = end_time - start_time
        print(f"Execution Time: {execution_time} seconds")
        self.__delete_images()

    def __predict(self, file_name: str) -> Tuple[Image.Image, float]:
        with Image.open(file_name) as image:
            image_np = np.array(image)
        output_image_np = self.__classifier.predict(image_np)
        output_image = Image.fromarray(output_image_np)
        output_image = output_image.resize(self.__image_size)

        self.__image_tk = ImageTk.PhotoImage(output_image)
        image_label = ttk.Label(self.__canvas, image=self.__image_tk)
        image_label.grid(row=0, column=0, sticky=(N, W, E, S))

    def __delete_images(self) -> None:
        for file_name in os.listdir():
            if file_name.split(".")[-1] == "jpg":
                os.remove(file_name)

    def __get_image_path(self) -> str:
        for file_name in os.listdir():
            if file_name.split(".")[-1] == "jpg":
                return file_name
        return None

    def run(self) -> None:
        self.__root.mainloop()


from math import sqrt, sin, cos, exp, pi

# data
k = 50000.0 ; m = 1200.00 ; z = 0.05
# p = 1900 + 200 t/t0
def pt(t,t0=0.5): return 1900.0+400.0*t if t<=t0 else 0.0

# time step
h = 0.02                       # time step

# derived system parameters
w2 = k/m ; wn = sqrt(w2) ; wd = wn * sqrt(1-z*z) ; c  = 2*m*wn*z

# magical constants for Linear Acceleration algorithm
k_hat = k + 3*c/h + 6*m/h/h
c_hat = 3*c + 6*m/h
m_hat = c*h/2 + 3*m
dx2dv = 3.0/h ; v2dv = 3.0 ; a2dv = h/2.0

# initial conditions
x = 0 ; v = 0 ; t = 0 ; p = pt(t)
a = p - c*v - k*x ; a = a/m

# print values, advance solution
while t<2+h/2:

    print (4*" %+014.8f") % (t, x*1000, v*1000, p)

    t1 = t+h
    p1 = pt(t1)
    dp = p1-p
    dp_hat = dp + c_hat*v + m_hat*a

    dx = dp_hat/k_hat
    dv = dx*dx2dv - v*v2dv - a*a2dv

    x = x + dx ; v = v +dv ; p = p1 ; t = t1
    a = p - c*v - k*x ; a = a/m


import csv
from util import connect_db

conn, cursor = connect_db("localhost", "root", "", "deteksi_trending_topik")

# Read the CSV file
with open('indonesian-news-title-200.csv', 'r', encoding='utf-8') as file:
    reader = csv.reader(file)
    header = next(reader)
    # Get the index of the second column
    judul_index = header.index('title')
    for row in reader:
        # Get the text from the second column
        judul = row[judul_index]
        # Insert the text into the database
        cursor.execute('''
            INSERT INTO dokumen (raw_text)
            VALUES (%s)
        ''', (judul,))

# Commit the changes and close the connection
conn.commit()
conn.close()


import logging

from src import app

logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)

application = app.create_app()

if __name__ == "__main__":
    logger.info("Starting the API ...")
    application.run(port=5001, host="0.0.0.0")


from flask import Flask, jsonify
app = Flask(__name__)

@app.route("/")
def home():
    return "
Home
"

@app.route("/test_json")
def test_json():
    """Function to test JSON return on web
    """
    name = "Chris"
    age = 34
    degrees = [
        {
            'first_degree': 'AAS Intelligence Operations',
            'second_degree': "BA Honors Economics with a Quantitative Emphasis, Math, Applied Math",
            'third_degree': "MS Quantitative Economics"
        }
    ]

    data = {
        'Name': name,
        'Age': age,
        'Degrees': degrees
    }
    return jsonify(data)

if __name__ == "__main__":
    app.run(debug=True, host="127.0.0.1")


"""
author:  Martin Rečka
email: martinrec@seznam.cz
discord: Martin Rečka#2020
"""

import sys
import csv
import bs4
import requests

def check_arguments():
    if len(sys.argv) < 3:
        print("Not enough arguments. Terminating the program.")
        exit()
    elif not sys.argv[1].startswith("https://volby.cz/pls/ps2017nss/ps3"):
        print("Wrong webpage. Terminating the program")
        exit()
    elif not sys.argv[2].endswith(".csv"):
        print("Wrong file suffix. Terminating the program.")
        exit()

def get_main_page():
    main_page = requests.get(sys.argv[1])
    if main_page.status_code == 200:
        return bs4.BeautifulSoup(main_page.text, "html.parser")
    else:
        print("Something is wrong. Terminating the program.")
        exit()

def get_code_list(main_page):
    continents = [
        "Evropa",
        "Asie",
        "Amerika",
        "Afrika",
        "Austrálie a Oceánie"
    ]
    code_list = []
    link_list = []
    all_links = main_page.find_all("a")
    for link in all_links:
        if link.text.isnumeric() and len(link.text) == 6 or link.text in continents:
            code_list.append(link.text)
            link_list.append("https://volby.cz/pls/ps2017nss/" + link["href"])
    return code_list, link_list

def get_header(preview_link):
    header = ["City code", "City name", "Eligible voters", "Issued envelopes", "Valid votes"]
    preview_page = requests.get(preview_link)
    preview_page_soup = bs4.BeautifulSoup(preview_page.text, "html.parser")
    for party in preview_page_soup.find_all("td")[10::5]:
        if party.text != "-":
            header.append(party.text)
    return header

def get_city_info(city_link, city_code):
    city_info = [city_code]
    city_page = requests.get(city_link)
    city_page_soup = bs4.BeautifulSoup(city_page.text, "html.parser")
    h3_number = len(city_page_soup.find_all("h3"))-3  # because of different number of h3 tags on Prague pages
    city_info.append(str(city_page_soup.find_all("h3")[h3_number].text).split(":")[1].strip())  # adds name of the city
    city_info.append("".join(str(city_page_soup.find_all("td")[3].text).split()))  # adds number of eligible voters
    city_info.append("".join(str(city_page_soup.find_all("td")[4].text).split()))  # adds number of issued envelopes
    city_info.append("".join(str(city_page_soup.find_all("td")[7].text).split()))  # adds number of valid votes
    for parti in city_page_soup.find_all("td")[11::5]:
        if parti.text != "-":  # because of empty lines in some tables
            city_info.append(parti.text)  # adds party results
    return city_info

def main():
    check_arguments()
    main_page = get_main_page()
    print("Downloading data from URL:", sys.argv[1])
    code_list, link_list = get_code_list(main_page)
    header = get_header(link_list[0])
    with open(sys.argv[2], "w", newline="") as file:
        print("Saving to file:", sys.argv[2])
        file_writer = csv.writer(file, delimiter=";")
        file_writer.writerow(header)
        for i in range(len(code_list)):
            file_writer.writerow(get_city_info(link_list[i], code_list[i]))
    print("Completed. Terminating the program.")

main()


from django.urls import path
from App import views

urlpatterns= [
    # path('admin/', admin.site.urls),
    path('', views.inicio, name="Inicio"),
    path('eventos', views.eventos, name="Eventos"),
    path('eventos/', views.eventos, name="EventosBuscar"),
    path('bandas', views.bandas, name="Bandas"),
    path('bandas/', views.bandas, name="BandasBuscar"),
    path('instrumentos', views.instrumentos, name="Instrumentos"),
    path('instrumentos/', views.instrumentos, name="InstrumentosBuscar")
]


import streamlit as st
from backend import *
from web3 import Web3

contract, contract_abi, contract_address, ganache_url = get_info()
web3 = Web3(Web3.HTTPProvider(ganache_url))
eth_price = get_eth_price()

def loanListing():
    loan_amount = st.slider('Pick an amount', 0, 10000)
    loan_in_eth = loan_amount / eth_price
    st.write("Amount in eth", loan_in_eth)

    amount_in_wei = int(loan_amount * 50735.67)

    interest_rate = 0
    termOptions = st.selectbox('Select term options in months', (1,3,6,12,18,24,30,36))

    if termOptions == 1:
        st.caption("Your interest rate will be 15%")
        interest_rate = 15

    elif termOptions == 3:
        st.caption("Your interest rate will be 12%" )
        interest_rate = 12

    elif  termOptions == 6:
        st.caption("Your interest rate will be 10%" )
        interest_rate = 10

    elif  termOptions == 12:
        st.caption("Your interest rate will be 8%" )
        interest_rate = 8

    elif  termOptions == 18:
        st.caption("Your interest rate will be 7%" )
        interest_rate = 7

    elif  termOptions == 24:
        st.caption("Your interest rate will be 6%" )
        interest_rate = 6

    elif  termOptions == 30:
        st.caption("Your interest rate will be 5%" )
        interest_rate = 5

    else :
        termOptions == 36
        st.caption("Your interest rate will be 4%" )
        interest_rate = 4

    if st.button('Create loan'):
        transaction = contract.functions.createLoan(amount_in_wei, interest_rate, termOptions).transact({'from': '0x906c2BeBdeBD7B388472999c4a972923302C1C34'})
        transaction_receipt = web3.eth.wait_for_transaction_receipt(transaction)
        tx_id = web3.eth.get_transaction_receipt
        st.caption("Success!")

def makePayment():
    amount = st.number_input('Enter payment amount ($)', 0, 10000) #figure out a way to no be able to pay more than the original loan is for
    amount_in_wei = int(amount * 50735.67)
    payment_in_eth = amount / eth_price
    st.write("Amount in eth", payment_in_eth)

    if st.button('Pay Now'):
        transaction = contract.functions.repayLoan(0).transact({'from': '0x906c2BeBdeBD7B388472999c4a972923302C1C34', 'value': amount_in_wei})
        transaction_receipt = web3.eth.wait_for_transaction_receipt(transaction)
        st.caption("Success!")

def view_detials():
    if st.button("Current Loan Details"):
        loan_details = contract.functions.getLoanDetails(0).call()
        print(loan_details)

def borrower():
    st.header("Welcome to the Lender page")
    st.subheader("Your wallet address: 0x906c2BeBdeBD7B388472999c4a972923302C1C34")
    loan_or_pay = st.selectbox("Are you here to create a loan listing or make a payment?", ["","Create loan listing", "Make Paymet", "Check Current Loan Details"])

    if loan_or_pay == "Create loan listing":
        loanListing()
    elif loan_or_pay == "Make Paymet":
        makePayment()
    elif loan_or_pay== "Check Current Loan Details":
        view_detials()
    else:
        print("select an option")


from collections import defaultdict, deque
from itertools import chain as iterator_chain

DIRECTIONS = deque([(0, -1), (1, 0), (0, 1), (-1, 0)])

def get_transformations(tile):
    transformations = []
    for _ in range(4):
        transformations.append(tile)
        transformations.append(tile[::-1])
        transformations.append([line[::-1] for line in tile])
        transformations.append([line[::-1] for line in tile][::-1])
        tile = [
            "".join(tile[x][y] for x in range(len(tile[0])))
            for y in range(len(tile))
        ]

    return transformations

def transform_tofit_left(tile, left_border):
    for tile in get_transformations(tile):
        if "".join(line[0] for line in tile) == left_border:
            return tile
    return None

def transform_tofit_top(tile, top_border):
    for tile in get_transformations(tile):
        if tile[0] == top_border:
            return tile
    return None

def build_sea_borders(sea, used, x, y):
    cur_tileid = sea[y][x]
    used[cur_tileid] = True

    if len(neighbors[cur_tileid]) == 2:
        DIRECTIONS.append(DIRECTIONS.popleft())

    for neighbor in neighbors[cur_tileid]:
        if not used[neighbor] and len(neighbors[neighbor]) < 4:

            dy, dx = DIRECTIONS[0]
            y += dy
            x += dx

            if len(sea) <= y:
                sea.append([None] * len(sea[0]))

            if len(sea[0]) <= x:
                for line in sea:
                    line.append(None)

            sea[y][x] = neighbor
            build_sea_borders(sea, used, x, y)
            return

tiles = {}
edges = {}
tile = []
tileid = None

with open("input.txt", 'r', encoding="utf-8") as file:
    for line in iterator_chain(file, [""]):
        line = line.strip()

        if not line:
            if tile:
                tilesize = len(tile)
                tiles[tileid] = tile
                edges[tileid] = set((
                    tile[0], tile[0][::-1],
                    tile[-1], tile[-1][::-1],
                    "".join(line[0] for line in tile), "".join(line[0] for line in tile)[::-1],
                    "".join(line[-1] for line in tile), "".join(line[-1] for line in tile)[::-1]
                ))

            tile = []

        elif line.startswith("Tile"):
            tileid = int(line.lstrip("Tile").rstrip(':'))

        else:
            tile.append(line)

neighbors = defaultdict(set)
for tileid1, edges1 in edges.items():
    for tileid2, edges2 in edges.items():

        if tileid1 == tileid2:
            continue

        if edges1 & edges2:
            neighbors[tileid1].add(tileid2)
            neighbors[tileid2].add(tileid1)

used = {tileid: False for tileid in edges}
sea = [[next(tile for tile, neighbor_edges in neighbors.items() if len(neighbor_edges) == 2)]]

build_sea_borders(sea, used, 0, 0)

sea_height, sea_width = len(sea), len(sea[0])

for y in range(1, sea_height - 1):
    for x in range(1, sea_width - 1):
        sea[y][x] = next(tileid
                         for tileid in neighbors[sea[y][x - 1]] & neighbors[sea[y - 1][x]]
                         if not used[tileid]
                         )
        used[sea[y][x]] = True

# -------------|  This is where part 1 ends  |--------------

posible_first_tiles = get_transformations(tiles[sea[0][0]])

for first_tile in posible_first_tiles:
    sea_tiles = [[None] * sea_width for _ in range(sea_height)]
    sea_tiles[0][0] = first_tile
    valid = True

    for x in range(1, sea_width):
        sea_tiles[0][x] = transform_tofit_left(
            tiles[sea[0][x]],
            left_border="".join(line[-1] for line in sea_tiles[0][x - 1])
        )
        if sea_tiles[0][x] is None:
            valid = False
            break

    if valid:
        for y in range(1, sea_height):
            for x in range(sea_width):
                sea_tiles[y][x] = transform_tofit_top(
                    tiles[sea[y][x]],
                    top_border=sea_tiles[y - 1][x][-1]
                )
                if sea_tiles[y][x] is None:
                    valid = False
                    break
            else:
                continue
            break

        else:
            break

# Removing borders:
sea_tiles = [
    [[line[1:-1] for line in sea_tiles[y][x][1:-1]] for x in range(sea_width)]
    for y in range(sea_height)
]
tilesize -= 2

# Building image:
image = []
cur_y = 0
for y in range(sea_height):
    image += [""] * tilesize
    for x in range(sea_width):
        for tile_y in range(tilesize):
            image[cur_y + tile_y] += sea_tiles[y][x][tile_y]

    cur_y += tilesize

# Searching for sea monsters:
with open("sea_monster.txt", 'r', encoding="utf-8") as file:
    sea_monster = [line.strip('\n') for line in file]

for image in get_transformations(image):
    free = [[image[y][x] == '#' for x in range(len(image[0]))] for y in range(len(image))]
    count = 0

    for y in range(len(image) - len(sea_monster)):
        for x in range(len(image[0]) - len(sea_monster[0])):
            for dy in range(len(sea_monster)):
                for dx in range(len(sea_monster[0])):
                    if sea_monster[dy][dx] == '#' and image[y + dy][x + dx] != '#':
                        break
                else:
                    continue
                break
            else:
                count += 1
                for dy in range(len(sea_monster)):
                    for dx in range(len(sea_monster[0])):
                        if sea_monster[dy][dx] == '#':
                            free[y + dy][x + dx] = False

    if count > 0:
        print(sum(sum(item for item in line) for line in free))
        break


t="sc4.txt"

with open(t,"r") as f:
    lines=f.readlines()
k=0

string = ["" for x in range(48)]
string2 = ["" for x in range(48)]

for i in range (4):
    for j in range(12):
        string[j+k]=(''.join(lines[k+j]))
    k+=12

for i in range (48):
    if(i!=0 and i!=12 and i!=24 and i!=36):
        string[i]=string[i].strip().split(":")
        string2[i]=string[i][1]
        if(i==11 or i ==23 or i==35 or i==47):
            print(string2[i])
            string2[i]=string2[i][:-8]
        string2[i]=string2[i].strip()

print(string2)
with open(t, "a") as f:
    f.write("\nAverage\n")
    for i in range (11):
        #f.write(string[i+1][0])
        k=(float(string2[i+1])+float(string2[i+13])+float(string2[i+25])+float(string2[i+37]))/4
        #print(k)
        f.write(string[i+1][0]+": "+str(k)+"\n")
    f.close()
#print(string2)
#print(string)


import math
import multiprocessing as mp
import pandas as pd
import re
import itertools

def product(sample, alphabet, k):
    return [''.join(p) for p in itertools.product(sample, *itertools.repeat(alphabet, k-1))]

def compute_kmer_table(is_reduced, method_dict, reduced_matrices, num_core):
    # Store representation method as key, K as value
    reduced_dict = {}
    # Store representation method as key, list of kmers as value
    kmers_dict = {}

    if('y' in is_reduced.lower()):
        for method in method_dict:
            if('y' in method_dict[method].lower()):
                reduced_dict[method] = method_dict[method].split(",")[1]

    else:
        reduced_dict['full'] = is_reduced.split(",")[1]

    for method in reduced_dict:
        kmers = []
        if not (method == 'full'):
            reduced_matrix = reduced_matrices[method]
            reduced_keys = set(reduced_matrix.keys())
            alphanumerics = 'abcdefghijklmnopqrstuvwxyz0123456789'
            representation = ''.join(set(alphanumerics).intersection(reduced_keys))
        else:
            representation = 'ACDEFGHIKLMNPQRSTVWY'

        lower_k = int(reduced_dict[method].split(":")[0])
        upper_k = int(reduced_dict[method].split(":")[1])

        # num_proc should be less than the length of representation
        num_proc = min(num_core, len(representation))
        part_size = math.ceil(len(representation) / num_proc)
        pool = mp.Pool(processes = num_proc)

        tmp = []
        for i in range(num_proc):
            if(i == num_proc - 1):
                sampled = representation[part_size * i:]
            else:
                sampled = representation[part_size * i: part_size * (i+1)]

            for i in range(lower_k, upper_k + 1):
                tmp.append(pool.apply_async(product, [sampled, representation, i]))

        pool.close()
        pool.join()

        # Unpack multiprocessing worker output
        result = [p.get() for p in tmp]
        kmers = [kmer for sublist in result for kmer in sublist]
        print("Total of {kmers} kmers for {method}".format(
            kmers=len(kmers),
            method=method
            ))
        kmers_dict[method] = kmers

    return kmers_dict

def calculate_length(reduced_seqs):
    """
    Get length of the sequence
    """
    for method in reduced_seqs:
        reduced_seqs[method]['length'] = reduced_seqs[method]['sequence'].str.len()

    return reduced_seqs

def calculate_frequency_par(reduced_seq, sampled_kmer_table):
    """
    helper function for calculate_kmer_frequency.
    It parallelizes kmer profile frequency calculation
    """
    df = pd.DataFrame(index=reduced_seq.index)

    for kmer in sampled_kmer_table:
        df[kmer] = reduced_seq['sequence'].apply(lambda x: len(re.findall('(?={0})'.format(kmer), x)))

    return df

def calculate_relative_frequency(reduced_seqs, kmer_tables, num_core):
    """
    Returns m by p K-mer frequency matrix

    m: Number of samples
    p: Number of K-mer profile
    """
    # list to store frequency dataframes
    kmer_freq_list = []

    print("calculating frequency")
    for method in reduced_seqs:
        print("Processing {}...".format(method))
        # store length column to be appended later
        length_col = reduced_seqs[method]['length']
        # retrieve corresponding kmer table
        kmer_table = kmer_tables[method]

        part_size = math.ceil(len(kmer_table) / num_core)

        pool = mp.Pool(processes = num_core)

        tmp = []
        for i in range(num_core):
            if(i == num_core - 1):
                sampled = kmer_table[part_size * i:]
            else:
                sampled = kmer_table[part_size * i: part_size * (i+1)]

            # run
            tmp.append(pool.apply_async(
                calculate_frequency_par, args=(reduced_seqs[method], sampled, )
                ))

        pool.close()
        pool.join()

        frames = [p.get() for p in tmp]

        freq_df = pd.concat(frames, axis=1)
        kmer_freq_list.append(freq_df)

    final_freq_df = pd.concat(kmer_freq_list, axis=1)
    final_freq_df['length'] = length_col
    print("calculating frequency done!")

    rel_freq_df = final_freq_df.apply(lambda x: x/x['length'],
            axis=1).drop('length', axis=1)

    return rel_freq_df


# structured query language
import csv

counts = {}
# counts = dict() another way of initialising dictionary
with open("sql-python.csv", "r") as file:
    reader = csv.DictReader(file)

    for row in reader:
        # print row["title"]
        title = row["title"]

        if title in counts:
            counts[title] += 1
        else:
            counts[title] = 1
    print(counts)
for title, count in sorted(counts.items(), key = lambda item: item[1], reverse = True):
    print(title, count, sep=" | ")