import sqlalchemy
import sqlalchemy.orm
import sqlalchemy.orm.collections

import cassiopeia.type.dto.common
import cassiopeia.type.core.common

@cassiopeia.type.core.common.inheritdocs
class MatchDetail(cassiopeia.type.dto.common.CassiopeiaDto):
    """
    mapId                    int                          match map ID
    matchCreation            int                          match creation time. Designates when the team select lobby is created and/or the match is made through match making, not when the game actually starts.
    matchDuration            int                          match duration
    matchId                  int                          ID of the match
    matchMode                str                          match mode (Legal values: CLASSIC, ODIN, ARAM, TUTORIAL, ONEFORALL, ASCENSION, FIRSTBLOOD, KINGPORO)
    matchType                str                          match type (Legal values: CUSTOM_GAME, MATCHED_GAME, TUTORIAL_GAME)
    matchVersion             str                          match version
    participantIdentities    list<ParticipantIdentity>    participant identity information
    participants             list<Participant>            participant information
    platformId               str                          platform ID of the match
    queueType                str                          match queue type (Legal values: CUSTOM, NORMAL_5x5_BLIND, RANKED_SOLO_5x5, RANKED_PREMADE_5x5, BOT_5x5, NORMAL_3x3, RANKED_PREMADE_3x3, NORMAL_5x5_DRAFT, ODIN_5x5_BLIND, ODIN_5x5_DRAFT, BOT_ODIN_5x5, BOT_5x5_INTRO, BOT_5x5_BEGINNER, BOT_5x5_INTERMEDIATE, RANKED_TEAM_3x3, RANKED_TEAM_5x5, BOT_TT_3x3, GROUP_FINDER_5x5, ARAM_5x5, ONEFORALL_5x5, FIRSTBLOOD_1x1, FIRSTBLOOD_2x2, SR_6x6, URF_5x5, ONEFORALL_MIRRORMODE_5x5, BOT_URF_5x5, NIGHTMARE_BOT_5x5_RANK1, NIGHTMARE_BOT_5x5_RANK2, NIGHTMARE_BOT_5x5_RANK5, ASCENSION_5x5, HEXAKILL, KING_PORO_5x5, COUNTER_PICK)
    region                   str                          region where the match was played
    season                   str                          season match was played (Legal values: PRESEASON3, SEASON3, PRESEASON2014, SEASON2014, PRESEASON2015, SEASON2015)
    teams                    list<Team>                   team information
    timeline                 Timeline                     match timeline data (not included by default)
    """
    def __init__(self, dictionary):
        self.mapId = dictionary.get("mapId", 0)
        self.matchCreation = dictionary.get("matchCreation", 0)
        self.matchDuration = dictionary.get("matchDuration", 0)
        self.matchId = dictionary.get("matchId", 0)
        self.matchMode = dictionary.get("matchMode", "")
        self.matchType = dictionary.get("matchType", "")
        self.matchVersion = dictionary.get("matchVersion", "")
        self.participantIdentities = [(ParticipantIdentity(pi) if not isinstance(pi, ParticipantIdentity) else pi) for pi in dictionary.get("participantIdentities", []) if pi]
        self.participants = [(Participant(p) if not isinstance(p, Participant) else p) for p in dictionary.get("participants", []) if p]
        self.platformId = dictionary.get("platformId", "")
        self.queueType = dictionary.get("queueType", "")
        self.region = dictionary.get("region", "")
        self.season = dictionary.get("season", "")
        self.teams = [(Team(t) if not isinstance(t, Team) else t) for t in dictionary.get("teams", []) if t]
        val = dictionary.get("timeline", None)
        self.timeline = Timeline(val) if val and not isinstance(val, Timeline) else val

    @property
    def item_ids(self):
        """Gets all item IDs contained in this object"""
        ids = set()
        for p in self.participants:
            s = p.stats
            if(s.item0):
                ids.add(s.item0)
            if(s.item1):
                ids.add(s.item1)
            if(s.item2):
                ids.add(s.item2)
            if(s.item3):
                ids.add(s.item3)
            if(s.item4):
                ids.add(s.item4)
            if(s.item5):
                ids.add(s.item5)
            if(s.item6):
                ids.add(s.item6)
        return ids

    @property
    def champion_ids(self):
        """Gets all champion IDs contained in this object"""
        ids = set()
        for p in self.participants:
            if(p.championId):
                ids.add(p.championId)
        for t in self.teams:
            for b in t.bans:
                if(b.championId):
                    ids.add(b.championId)
        return ids

    @property
    def mastery_ids(self):
        """Gets all mastery IDs contained in this object"""
        ids = set()
        for p in self.participants:
            for m in p.masteries:
                if(m.masteryId):
                    ids.add(m.masteryId)
        return ids

    @property
    def rune_ids(self):
        """Gets all rune IDs contained in this object"""
        ids = set()
        for p in self.participants:
            for r in p.runes:
                if(r.runeId):
                    ids.add(r.runeId)
        return ids

    @property
    def summoner_ids(self):
        """Gets all summoner IDs contained in this object"""
        ids = set()
        for p in self.participantIdentities:
            if(p.player and p.player.summonerId):
                ids.add(p.player.summonerId)
        return ids

    @property
    def summoner_spell_ids(self):
        """Gets all summoner spell IDs contained in this object"""
        ids = set()
        for p in self.participants:
            if(p.spell1Id):
                ids.add(p.spell1Id)
            if(p.spell2Id):
                ids.add(p.spell2Id)
        return ids


@cassiopeia.type.core.common.inheritdocs
class Participant(cassiopeia.type.dto.common.CassiopeiaDto):
    """
    championId                   int                    champion ID
    highestAchievedSeasonTier    str                    highest ranked tier achieved for the previous season, if any, otherwise null. Used to display border in game loading screen. (Legal values: CHALLENGER, MASTER, DIAMOND, PLATINUM, GOLD, SILVER, BRONZE, UNRANKED)
    masteries                    list<Mastery>          list of mastery information
    participantId                int                    participant ID
    runes                        list<Rune>             list of rune information
    spell1Id                     int                    first summoner spell ID
    spell2Id                     int                    second summoner spell ID
    stats                        ParticipantStats       participant statistics
    teamId                       int                    team ID
    timeline                     ParticipantTimeline    timeline data. Delta fields refer to values for the specified period (e.g., the gold per minute over the first 10 minutes of the game versus the second 20 minutes of the game. Diffs fields refer to the deltas versus the calculated lane opponent(s).
    """
    def __init__(self, dictionary):
        self.championId = dictionary.get("championId", 0)
        self.highestAchievedSeasonTier = dictionary.get("highestAchievedSeasonTier", "")
        self.masteries = [(Mastery(m) if not isinstance(m, Mastery) else m) for m in dictionary.get("masteries", []) if m]
        self.participantId = dictionary.get("participantId", 0)
        self.runes = [(Rune(r) if not isinstance(r, Rune) else r) for r in dictionary.get("runes", []) if r]
        self.spell1Id = dictionary.get("spell1Id", 0)
        self.spell2Id = dictionary.get("spell2Id", 0)
        val = dictionary.get("stats", None)
        self.stats = ParticipantStats(val) if val and not isinstance(val, ParticipantStats) else val
        self.teamId = dictionary.get("teamId", 0)
        val = dictionary.get("timeline", None)
        self.timeline = ParticipantTimeline(val) if val and not isinstance(val, ParticipantTimeline) else val


@cassiopeia.type.core.common.inheritdocs
class ParticipantIdentity(cassiopeia.type.dto.common.CassiopeiaDto):
    """
    participantId    int       participant ID
    player           Player    player information
    """
    def __init__(self, dictionary):
        self.participantId = dictionary.get("participantId", 0)
        val = dictionary.get("player", None)
        self.player = Player(val) if val and not isinstance(val, Player) else val


@cassiopeia.type.core.common.inheritdocs
class Team(cassiopeia.type.dto.common.CassiopeiaDto):
    """
    bans                    list<BannedChampion>    if game was draft mode, contains banned champion data, otherwise null
    baronKills              int                     number of times the team killed baron
    dominionVictoryScore    int                     if game was a dominion game, specifies the points the team had at game end, otherwise null
    dragonKills             int                     number of times the team killed dragon
    firstBaron              bool                    flag indicating whether or not the team got the first baron kill
    firstBlood              bool                    flag indicating whether or not the team got first blood
    firstDragon             bool                    flag indicating whether or not the team got the first dragon kill
    firstInhibitor          bool                    flag indicating whether or not the team destroyed the first inhibitor
    firstTower              bool                    flag indicating whether or not the team destroyed the first tower
    inhibitorKills          int                     number of inhibitors the team destroyed
    teamId                  int                     team ID
    towerKills              int                     number of towers the team destroyed
    vilemawKills            int                     number of times the team killed vilemaw
    winner                  bool                    flag indicating whether or not the team won
    """
    def __init__(self, dictionary):
        self.bans = [(BannedChampion(c) if not isinstance(c, BannedChampion) else c) for c in dictionary.get("bans", []) if c]
        self.baronKills = dictionary.get("baronKills", 0)
        self.dominionVictoryScore = dictionary.get("dominionVictoryScore", 0)
        self.dragonKills = dictionary.get("dragonKills", 0)
        self.firstBaron = dictionary.get("firstBaron", False)
        self.firstBlood = dictionary.get("firstBlood", False)
        self.firstDragon = dictionary.get("firstDragon", False)
        self.firstInhibitor = dictionary.get("firstInhibitor", False)
        self.firstTower = dictionary.get("firstTower", False)
        self.inhibitorKills = dictionary.get("inhibitorKills", 0)
        self.teamId = dictionary.get("teamId", 0)
        self.towerKills = dictionary.get("towerKills", 0)
        self.vilemawKills = dictionary.get("vilemawKills", 0)
        self.winner = dictionary.get("winner", False)


@cassiopeia.type.core.common.inheritdocs
class Timeline(cassiopeia.type.dto.common.CassiopeiaDto):
    """
    frameInterval    int            time between each returned frame in milliseconds
    frames           list<Frame>    list of timeline frames for the game
    """
    def __init__(self, dictionary):
        self.frameInterval = dictionary.get("frameInterval", 0)
        self.frames = [(Frame(f) if not isinstance(f, Frame) else f) for f in dictionary.get("frames", []) if f]


@cassiopeia.type.core.common.inheritdocs
class Mastery(cassiopeia.type.dto.common.CassiopeiaDto):
    """
    masteryId    int    mastery ID
    rank         int    mastery rank
    """
    def __init__(self, dictionary):
        self.masteryId = dictionary.get("masteryId", 0)
        self.rank = dictionary.get("rank", 0)


@cassiopeia.type.core.common.inheritdocs
class ParticipantStats(cassiopeia.type.dto.common.CassiopeiaDto):
    """
    assists                            int     number of assists
    champLevel                         int     champion level achieved
    combatPlayerScore                  int     if game was a dominion game, player's combat score, otherwise 0
    deaths                             int     number of deaths
    doubleKills                        int     number of double kills
    firstBloodAssist                   bool    flag indicating if participant got an assist on first blood
    firstBloodKill                     bool    flag indicating if participant got first blood
    firstInhibitorAssist               bool    flag indicating if participant got an assist on the first inhibitor
    firstInhibitorKill                 bool    flag indicating if participant destroyed the first inhibitor
    firstTowerAssist                   bool    flag indicating if participant got an assist on the first tower
    firstTowerKill                     bool    flag indicating if participant destroyed the first tower
    goldEarned                         int     gold earned
    goldSpent                          int     gold spent
    inhibitorKills                     int     number of inhibitor kills
    item0                              int     frst item ID
    item1                              int     second item ID
    item2                              int     third item ID
    item3                              int     fourth item ID
    item4                              int     fifth item ID
    item5                              int     sixth item ID
    item6                              int     seventh item ID
    killingSprees                      int     number of killing sprees
    kills                              int     number of kills
    largestCriticalStrike              int     largest critical strike
    largestKillingSpree                int     largest killing spree
    largestMultiKill                   int     largest multi kill
    magicDamageDealt                   int     magical damage dealt
    magicDamageDealtToChampions        int     magical damage dealt to champions
    magicDamageTaken                   int     magic damage taken
    minionsKilled                      int     minions killed
    neutralMinionsKilled               int     neutral minions killed
    neutralMinionsKilledEnemyJungle    int     neutral jungle minions killed in the enemy team's jungle
    neutralMinionsKilledTeamJungle     int     neutral jungle minions killed in your team's jungle
    nodeCapture                        int     if game was a dominion game, number of node captures
    nodeCaptureAssist                  int     if game was a dominion game, number of node capture assists
    nodeNeutralize                     int     if game was a dominion game, number of node neutralizations
    nodeNeutralizeAssist               int     if game was a dominion game, number of node neutralization assists
    objectivePlayerScore               int     if game was a dominion game, player's objectives score, otherwise 0
    pentaKills                         int     number of penta kills
    physicalDamageDealt                int     physical damage dealt
    physicalDamageDealtToChampions     int     physical damage dealt to champions
    physicalDamageTaken                int     physical damage taken
    quadraKills                        int     number of quadra kills
    sightWardsBoughtInGame             int     sight wards purchased
    teamObjective                      int     if game was a dominion game, number of completed team objectives (i.e., quests)
    totalDamageDealt                   int     total damage dealt
    totalDamageDealtToChampions        int     total damage dealt to champions
    totalDamageTaken                   int     total damage taken
    totalHeal                          int     total heal amount
    totalPlayerScore                   int     if game was a dominion game, player's total score, otherwise 0
    totalScoreRank                     int     if game was a dominion game, team rank of the player's total score (e.g., 1-5)
    totalTimeCrowdControlDealt         int     total dealt crowd control time
    totalUnitsHealed                   int     total units healed
    towerKills                         int     number of tower kills
    tripleKills                        int     number of triple kills
    trueDamageDealt                    int     true damage dealt
    trueDamageDealtToChampions         int     true damage dealt to champions
    trueDamageTaken                    int     true damage taken
    unrealKills                        int     number of unreal kills
    visionWardsBoughtInGame            int     vision wards purchased
    wardsKilled                        int     number of wards killed
    wardsPlaced                        int     number of wards placed
    winner                             bool    flag indicating whether or not the participant won
    """
    def __init__(self, dictionary):
        self.assists = dictionary.get("assists", 0)
        self.champLevel = dictionary.get("champLevel", 0)
        self.combatPlayerScore = dictionary.get("combatPlayerScore", 0)
        self.deaths = dictionary.get("deaths", 0)
        self.doubleKills = dictionary.get("doubleKills", 0)
        self.firstBloodAssist = dictionary.get("firstBloodAssist", False)
        self.firstBloodKill = dictionary.get("firstBloodKill", False)
        self.firstInhibitorAssist = dictionary.get("firstInhibitorAssist", False)
        self.firstInhibitorKill = dictionary.get("firstInhibitorKill", False)
        self.firstTowerAssist = dictionary.get("firstTowerAssist", False)
        self.firstTowerKill = dictionary.get("firstTowerKill", False)
        self.goldEarned = dictionary.get("goldEarned", 0)
        self.goldSpent = dictionary.get("goldSpent", 0)
        self.inhibitorKills = dictionary.get("inhibitorKills", 0)
        self.item0 = dictionary.get("item0", 0)
        self.item1 = dictionary.get("item1", 0)
        self.item2 = dictionary.get("item2", 0)
        self.item3 = dictionary.get("item3", 0)
        self.item4 = dictionary.get("item4", 0)
        self.item5 = dictionary.get("item5", 0)
        self.item6 = dictionary.get("item6", 0)
        self.killingSprees = dictionary.get("killingSprees", 0)
        self.kills = dictionary.get("kills", 0)
        self.largestCriticalStrike = dictionary.get("largestCriticalStrike", 0)
        self.largestKillingSpree = dictionary.get("largestKillingSpree", 0)
        self.largestMultiKill = dictionary.get("largestMultiKill", 0)
        self.magicDamageDealt = dictionary.get("magicDamageDealt", 0)
        self.magicDamageDealtToChampions = dictionary.get("magicDamageDealtToChampions", 0)
        self.magicDamageTaken = dictionary.get("magicDamageTaken", 0)
        self.minionsKilled = dictionary.get("minionsKilled", 0)
        self.neutralMinionsKilled = dictionary.get("neutralMinionsKilled", 0)
        self.neutralMinionsKilledEnemyJungle = dictionary.get("neutralMinionsKilledEnemyJungle", 0)
        self.neutralMinionsKilledTeamJungle = dictionary.get("neutralMinionsKilledTeamJungle", 0)
        self.nodeCapture = dictionary.get("nodeCapture", 0)
        self.nodeCaptureAssist = dictionary.get("nodeCaptureAssist", 0)
        self.nodeNeutralize = dictionary.get("nodeNeutralize", 0)
        self.nodeNeutralizeAssist = dictionary.get("nodeNeutralizeAssist", 0)
        self.objectivePlayerScore = dictionary.get("objectivePlayerScore", 0)
        self.pentaKills = dictionary.get("pentaKills", 0)
        self.physicalDamageDealt = dictionary.get("physicalDamageDealt", 0)
        self.physicalDamageDealtToChampions = dictionary.get("physicalDamageDealtToChampions", 0)
        self.physicalDamageTaken = dictionary.get("physicalDamageTaken", 0)
        self.quadraKills = dictionary.get("quadraKills", 0)
        self.sightWardsBoughtInGame = dictionary.get("sightWardsBoughtInGame", 0)
        self.teamObjective = dictionary.get("teamObjective", 0)
        self.totalDamageDealt = dictionary.get("totalDamageDealt", 0)
        self.totalDamageDealtToChampions = dictionary.get("totalDamageDealtToChampions", 0)
        self.totalDamageTaken = dictionary.get("totalDamageTaken", 0)
        self.totalHeal = dictionary.get("totalHeal", 0)
        self.totalPlayerScore = dictionary.get("totalPlayerScore", 0)
        self.totalScoreRank = dictionary.get("totalScoreRank", 0)
        self.totalTimeCrowdControlDealt = dictionary.get("totalTimeCrowdControlDealt", 0)
        self.totalUnitsHealed = dictionary.get("totalUnitsHealed", 0)
        self.towerKills = dictionary.get("towerKills", 0)
        self.tripleKills = dictionary.get("tripleKills", 0)
        self.trueDamageDealt = dictionary.get("trueDamageDealt", 0)
        self.trueDamageDealtToChampions = dictionary.get("trueDamageDealtToChampions", 0)
        self.trueDamageTaken = dictionary.get("trueDamageTaken", 0)
        self.unrealKills = dictionary.get("unrealKills", 0)
        self.visionWardsBoughtInGame = dictionary.get("visionWardsBoughtInGame", 0)
        self.wardsKilled = dictionary.get("wardsKilled", 0)
        self.wardsPlaced = dictionary.get("wardsPlaced", 0)
        self.winner = dictionary.get("winner", False)


@cassiopeia.type.core.common.inheritdocs
class ParticipantTimeline(cassiopeia.type.dto.common.CassiopeiaDto):
    """
    ancientGolemAssistsPerMinCounts    ParticipantTimelineData    ancient golem assists per minute timeline counts
    ancientGolemKillsPerMinCounts      ParticipantTimelineData    ancient golem kills per minute timeline counts
    assistedLaneDeathsPerMinDeltas     ParticipantTimelineData    assisted lane deaths per minute timeline data
    assistedLaneKillsPerMinDeltas      ParticipantTimelineData    assisted lane kills per minute timeline data
    baronAssistsPerMinCounts           ParticipantTimelineData    baron assists per minute timeline counts
    baronKillsPerMinCounts             ParticipantTimelineData    baron kills per minute timeline counts
    creepsPerMinDeltas                 ParticipantTimelineData    creeps per minute timeline data
    csDiffPerMinDeltas                 ParticipantTimelineData    creep score difference per minute timeline data
    damageTakenDiffPerMinDeltas        ParticipantTimelineData    damage taken difference per minute timeline data
    damageTakenPerMinDeltas            ParticipantTimelineData    damage taken per minute timeline data
    dragonAssistsPerMinCounts          ParticipantTimelineData    dragon assists per minute timeline counts
    dragonKillsPerMinCounts            ParticipantTimelineData    dragon kills per minute timeline counts
    elderLizardAssistsPerMinCounts     ParticipantTimelineData    elder lizard assists per minute timeline counts
    elderLizardKillsPerMinCounts       ParticipantTimelineData    elder lizard kills per minute timeline counts
    goldPerMinDeltas                   ParticipantTimelineData    gold per minute timeline data
    inhibitorAssistsPerMinCounts       ParticipantTimelineData    inhibitor assists per minute timeline counts
    inhibitorKillsPerMinCounts         ParticipantTimelineData    inhibitor kills per minute timeline counts
    lane                               str                        participant's lane (Legal values: MID, MIDDLE, TOP, JUNGLE, BOT, BOTTOM)
    role                               str                        participant's role (Legal values: DUO, NONE, SOLO, DUO_CARRY, DUO_SUPPORT)
    towerAssistsPerMinCounts           ParticipantTimelineData    tower assists per minute timeline counts
    towerKillsPerMinCounts             ParticipantTimelineData    tower kills per minute timeline counts
    towerKillsPerMinDeltas             ParticipantTimelineData    tower kills per minute timeline data
    vilemawAssistsPerMinCounts         ParticipantTimelineData    vilemaw assists per minute timeline counts
    vilemawKillsPerMinCounts           ParticipantTimelineData    vilemaw kills per minute timeline counts
    wardsPerMinDeltas                  ParticipantTimelineData    wards placed per minute timeline data
    xpDiffPerMinDeltas                 ParticipantTimelineData    experience difference per minute timeline data
    xpPerMinDeltas                     ParticipantTimelineData    experience per minute timeline data
    """
    def __init__(self, dictionary):
        val = dictionary.get("ancientGolemAssistsPerMinCounts", None)
        self.ancientGolemAssistsPerMinCounts = ParticipantTimelineData(val, "ancientGolemAssistsPerMinCounts") if val and not isinstance(val, ParticipantTimelineData) else val
        val = dictionary.get("ancientGolemKillsPerMinCounts", None)
        self.ancientGolemKillsPerMinCounts = ParticipantTimelineData(val, "ancientGolemKillsPerMinCounts") if val and not isinstance(val, ParticipantTimelineData) else val
        val = dictionary.get("assistedLaneDeathsPerMinDeltas", None)
        self.assistedLaneDeathsPerMinDeltas = ParticipantTimelineData(val, "assistedLaneDeathsPerMinDeltas") if val and not isinstance(val, ParticipantTimelineData) else val
        val = dictionary.get("assistedLaneKillsPerMinDeltas", None)
        self.assistedLaneKillsPerMinDeltas = ParticipantTimelineData(val, "assistedLaneKillsPerMinDeltas") if val and not isinstance(val, ParticipantTimelineData) else val
        val = dictionary.get("baronAssistsPerMinCounts", None)
        self.baronAssistsPerMinCounts = ParticipantTimelineData(val, "baronAssistsPerMinCounts") if val and not isinstance(val, ParticipantTimelineData) else val
        val = dictionary.get("baronKillsPerMinCounts", None)
        self.baronKillsPerMinCounts = ParticipantTimelineData(val, "baronKillsPerMinCounts") if val and not isinstance(val, ParticipantTimelineData) else val
        val = dictionary.get("creepsPerMinDeltas", None)
        self.creepsPerMinDeltas = ParticipantTimelineData(val, "creepsPerMinDeltas") if val and not isinstance(val, ParticipantTimelineData) else val
        val = dictionary.get("csDiffPerMinDeltas", None)
        self.csDiffPerMinDeltas = ParticipantTimelineData(val, "csDiffPerMinDeltas") if val and not isinstance(val, ParticipantTimelineData) else val
        val = dictionary.get("damageTakenDiffPerMinDeltas", None)
        self.damageTakenDiffPerMinDeltas = ParticipantTimelineData(val, "damageTakenDiffPerMinDeltas") if val and not isinstance(val, ParticipantTimelineData) else val
        val = dictionary.get("damageTakenPerMinDeltas", None)
        self.damageTakenPerMinDeltas = ParticipantTimelineData(val, "damageTakenPerMinDeltas") if val and not isinstance(val, ParticipantTimelineData) else val
        val = dictionary.get("dragonAssistsPerMinCounts", None)
        self.dragonAssistsPerMinCounts = ParticipantTimelineData(val, "dragonAssistsPerMinCounts") if val and not isinstance(val, ParticipantTimelineData) else val
        val = dictionary.get("dragonKillsPerMinCounts", None)
        self.dragonKillsPerMinCounts = ParticipantTimelineData(val, "dragonKillsPerMinCounts") if val and not isinstance(val, ParticipantTimelineData) else val
        val = dictionary.get("elderLizardAssistsPerMinCounts", None)
        self.elderLizardAssistsPerMinCounts = ParticipantTimelineData(val, "elderLizardAssistsPerMinCounts") if val and not isinstance(val, ParticipantTimelineData) else val
        val = dictionary.get("elderLizardKillsPerMinCounts", None)
        self.elderLizardKillsPerMinCounts = ParticipantTimelineData(val, "elderLizardKillsPerMinCounts") if val and not isinstance(val, ParticipantTimelineData) else val
        val = dictionary.get("goldPerMinDeltas", None)
        self.goldPerMinDeltas = ParticipantTimelineData(val, "goldPerMinDeltas") if val and not isinstance(val, ParticipantTimelineData) else val
        val = dictionary.get("inhibitorAssistsPerMinCounts", None)
        self.inhibitorAssistsPerMinCounts = ParticipantTimelineData(val, "inhibitorAssistsPerMinCounts") if val and not isinstance(val, ParticipantTimelineData) else val
        val = dictionary.get("inhibitorKillsPerMinCounts", None)
        self.inhibitorKillsPerMinCounts = ParticipantTimelineData(val, "inhibitorKillsPerMinCounts") if val and not isinstance(val, ParticipantTimelineData) else val
        self.lane = dictionary.get("lane", "")
        self.role = dictionary.get("role", "")
        val = dictionary.get("towerAssistsPerMinCounts", None)
        self.towerAssistsPerMinCounts = ParticipantTimelineData(val, "towerAssistsPerMinCounts") if val and not isinstance(val, ParticipantTimelineData) else val
        val = dictionary.get("towerKillsPerMinCounts", None)
        self.towerKillsPerMinCounts = ParticipantTimelineData(val, "towerKillsPerMinCounts") if val and not isinstance(val, ParticipantTimelineData) else val
        val = dictionary.get("towerKillsPerMinDeltas", None)
        self.towerKillsPerMinDeltas = ParticipantTimelineData(val, "towerKillsPerMinDeltas") if val and not isinstance(val, ParticipantTimelineData) else val
        val = dictionary.get("vilemawAssistsPerMinCounts", None)
        self.vilemawAssistsPerMinCounts = ParticipantTimelineData(val, "vilemawAssistsPerMinCounts") if val and not isinstance(val, ParticipantTimelineData) else val
        val = dictionary.get("vilemawKillsPerMinCounts", None)
        self.vilemawKillsPerMinCounts = ParticipantTimelineData(val, "vilemawKillsPerMinCounts") if val and not isinstance(val, ParticipantTimelineData) else val
        val = dictionary.get("wardsPerMinDeltas", None)
        self.wardsPerMinDeltas = ParticipantTimelineData(val, "wardsPerMinDeltas") if val and not isinstance(val, ParticipantTimelineData) else val
        val = dictionary.get("xpDiffPerMinDeltas", None)
        self.xpDiffPerMinDeltas = ParticipantTimelineData(val, "xpDiffPerMinDeltas") if val and not isinstance(val, ParticipantTimelineData) else val
        val = dictionary.get("xpPerMinDeltas", None)
        self.xpPerMinDeltas = ParticipantTimelineData(val, "xpPerMinDeltas") if val and not isinstance(val, ParticipantTimelineData) else val


@cassiopeia.type.core.common.inheritdocs
class Rune(cassiopeia.type.dto.common.CassiopeiaDto):
    """
    rank      int    rune rank
    runeId    int    rune ID
    """
    def __init__(self, dictionary):
        self.rank = dictionary.get("rank", 0)
        self.runeId = dictionary.get("runeId", 0)


@cassiopeia.type.core.common.inheritdocs
class Player(cassiopeia.type.dto.common.CassiopeiaDto):
    """
    matchHistoryUri    str    match history URI
    profileIcon        int    profile icon ID
    summonerId         int    summoner ID
    summonerName       str    summoner name
    """
    def __init__(self, dictionary):
        self.matchHistoryUri = dictionary.get("matchHistoryUri", "")
        self.profileIcon = dictionary.get("profileIcon", 0)
        self.summonerId = dictionary.get("summonerId", 0)
        self.summonerName = dictionary.get("summonerName", "")


@cassiopeia.type.core.common.inheritdocs
class BannedChampion(cassiopeia.type.dto.common.CassiopeiaDto):
    """
    championId    int    banned champion ID
    pickTurn      int    turn during which the champion was banned
    """
    def __init__(self, dictionary):
        self.championId = dictionary.get("championId", 0)
        self.pickTurn = dictionary.get("pickTurn", 0)


@cassiopeia.type.core.common.inheritdocs
class Frame(cassiopeia.type.dto.common.CassiopeiaDto):
    """
    events               list<Event>                    list of events for this frame
    participantFrames    dict<str, ParticipantFrame>    map of each participant ID to the participant's information for the frame
    timestamp            int                            represents how many milliseconds into the game the frame occurred
    """
    def __init__(self, dictionary):
        self.events = [(Event(e) if not isinstance(e, Event) else e) for e in dictionary.get("events", []) if e]
        self.participantFrames = {i: ParticipantFrame(pf) if not isinstance(pf, ParticipantFrame) else pf for i, pf in dictionary.get("participantFrames", {}).items()}
        self.timestamp = dictionary.get("timestamp", 0)


@cassiopeia.type.core.common.inheritdocs
class ParticipantTimelineData(cassiopeia.type.dto.common.CassiopeiaDto):
    """
    events               list<Event>                    list of events for this frame
    participantFrames    dict<str, ParticipantFrame>    map of each participant ID to the participant's information for the frame
    timestamp            int                            represents how many milliseconds into the game the frame occurred
    tenToTwenty          float                          value per minute from 10 min to 20 min
    thirtyToEnd          float                          value per minute from 30 min to the end of the game
    twentyToThirty       float                          value per minute from 20 min to 30 min
    zeroToTen            float                          value per minute from the beginning of the game to 10 min
    """
    def __init__(self, dictionary, type_=None):
        self.tenToTwenty = dictionary.get("tenToTwenty", 0.0)
        self.thirtyToEnd = dictionary.get("thirtyToEnd", 0.0)
        self.twentyToThirty = dictionary.get("twentyToThirty", 0.0)
        self.zeroToTen = dictionary.get("zeroToTen", 0.0)
        self._type = type_


@cassiopeia.type.core.common.inheritdocs
class Event(cassiopeia.type.dto.common.CassiopeiaDto):
    """
    ascendedType               str          the ascended type of the event. Only present if relevant. Note that CLEAR_ASCENDED refers to when a participants kills the ascended player. (Legal values: CHAMPION_ASCENDED, CLEAR_ASCENDED, MINION_ASCENDED)
    assistingParticipantIds    list<int>    the assisting participant IDs of the event. Only present if relevant.
    buildingType               str          the building type of the event. Only present if relevant. (Legal values: INHIBITOR_BUILDING, TOWER_BUILDING)
    creatorId                  int          the creator ID of the event. Only present if relevant.
    eventType                  str          event type (Legal values: ASCENDED_EVENT, BUILDING_KILL, CAPTURE_POINT, CHAMPION_KILL, ELITE_MONSTER_KILL, ITEM_DESTROYED, ITEM_PURCHASED, ITEM_SOLD, ITEM_UNDO, PORO_KING_SUMMON, SKILL_LEVEL_UP, WARD_KILL, WARD_PLACED)
    itemAfter                  int          the ending item ID of the event. Only present if relevant.
    itemBefore                 int          the starting item ID of the event. Only present if relevant.
    itemId                     int          the item ID of the event. Only present if relevant.
    killerId                   int          the killer ID of the event. Only present if relevant. Killer ID 0 indicates a minion.
    laneType                   str          the lane type of the event. Only present if relevant. (Legal values: BOT_LANE, MID_LANE, TOP_LANE)
    levelUpType                str          the level up type of the event. Only present if relevant. (Legal values: EVOLVE, NORMAL)
    monsterType                str          the monster type of the event. Only present if relevant. (Legal values: BARON_NASHOR, BLUE_GOLEM, DRAGON, RED_LIZARD, VILEMAW)
    participantId              int          the participant ID of the event. Only present if relevant.
    pointCaptured              str          the point captured in the event. Only present if relevant. (Legal values: POINT_A, POINT_B, POINT_C, POINT_D, POINT_E)
    position                   Position     the position of the event. Only present if relevant.
    skillSlot                  int          the skill slot of the event. Only present if relevant.
    teamId                     int          the team ID of the event. Only present if relevant.
    timestamp                  int          represents how many milliseconds into the game the event occurred.
    towerType                  str          the tower type of the event. Only present if relevant. (Legal values: BASE_TURRET, FOUNTAIN_TURRET, INNER_TURRET, NEXUS_TURRET, OUTER_TURRET, UNDEFINED_TURRET)
    victimId                   int          the victim ID of the event. Only present if relevant.
    wardType                   str          the ward type of the event. Only present if relevant. (Legal values: SIGHT_WARD, TEEMO_MUSHROOM, UNDEFINED, VISION_WARD, YELLOW_TRINKET, YELLOW_TRINKET_UPGRADE)
    """
    def __init__(self, dictionary):
        self.ascendedType = dictionary.get("ascendedType", "")
        self.assistingParticipantIds = dictionary.get("assistingParticipantIds", [])
        self.buildingType = dictionary.get("buildingType", "")
        self.creatorId = dictionary.get("creatorId", 0)
        self.eventType = dictionary.get("eventType", "")
        self.itemAfter = dictionary.get("itemAfter", 0)
        self.itemBefore = dictionary.get("itemBefore", 0)
        self.itemId = dictionary.get("itemId", 0)
        self.killerId = dictionary.get("killerId", 0)
        self.laneType = dictionary.get("laneType", "")
        self.levelUpType = dictionary.get("levelUpType", "")
        self.monsterType = dictionary.get("monsterType", "")
        self.participantId = dictionary.get("participantId", 0)
        self.pointCaptured = dictionary.get("pointCaptured", "")
        val = dictionary.get("position", None)
        self.position = Position(val) if val and not isinstance(val, Position) else val
        self.skillSlot = dictionary.get("skillSlot", 0)
        self.teamId = dictionary.get("teamId", 0)
        self.timestamp = dictionary.get("timestamp", 0)
        self.towerType = dictionary.get("towerType", "")
        self.victimId = dictionary.get("victimId", 0)
        self.wardType = dictionary.get("wardType", "")


@cassiopeia.type.core.common.inheritdocs
class ParticipantFrame(cassiopeia.type.dto.common.CassiopeiaDto):
    """
    currentGold            int         participant's current gold
    dominionScore          int         dominion score of the participant
    jungleMinionsKilled    int         number of jungle minions killed by participant
    level                  int         participant's current level
    minionsKilled          int         number of minions killed by participant
    participantId          int         participant ID
    position               Position    participant's position
    teamScore              int         team score of the participant
    totalGold              int         participant's total gold
    xp                     int         experience earned by participant
    """
    def __init__(self, dictionary):
        self.currentGold = dictionary.get("currentGold", 0)
        self.dominionScore = dictionary.get("dominionScore", 0)
        self.jungleMinionsKilled = dictionary.get("jungleMinionsKilled", 0)
        self.level = dictionary.get("level", 0)
        self.minionsKilled = dictionary.get("minionsKilled", 0)
        self.participantId = dictionary.get("participantId", 0)
        val = dictionary.get("position", None)
        self.position = Position(val) if val and not isinstance(val, Position) else val
        self.teamScore = dictionary.get("teamScore", 0)
        self.totalGold = dictionary.get("totalGold", 0)
        self.xp = dictionary.get("xp", 0)


@cassiopeia.type.core.common.inheritdocs
class Position(cassiopeia.type.dto.common.CassiopeiaDto):
    """
    x    int    x position
    y    int    y position
    """
    def __init__(self, dictionary):
        self.x = dictionary.get("x", 0)
        self.y = dictionary.get("y", 0)

###############################
# Dynamic SQLAlchemy bindings #
###############################

def _sa_bind_match_detail():
    global MatchDetail
    @cassiopeia.type.core.common.inheritdocs
    class MatchDetail(MatchDetail, cassiopeia.type.dto.common.BaseDB):
        __tablename__ = "MatchDetail"
        mapId = sqlalchemy.Column(sqlalchemy.Integer)
        matchCreation = sqlalchemy.Column(sqlalchemy.BigInteger)
        matchDuration = sqlalchemy.Column(sqlalchemy.Integer)
        matchId = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
        matchMode = sqlalchemy.Column(sqlalchemy.String(30))
        matchType = sqlalchemy.Column(sqlalchemy.String(30))
        matchVersion = sqlalchemy.Column(sqlalchemy.String(30))
        participantIdentities = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantIdentity", cascade="all, delete-orphan", passive_deletes=True)
        participants = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.Participant", cascade="all, delete-orphan", passive_deletes=True)
        platformId = sqlalchemy.Column(sqlalchemy.String(30))
        queueType = sqlalchemy.Column(sqlalchemy.String(30))
        region = sqlalchemy.Column(sqlalchemy.String(30))
        season = sqlalchemy.Column(sqlalchemy.String(30))
        teams = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.Team", cascade="all, delete-orphan", passive_deletes=True)
        timeline = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.Timeline", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        
def _sa_bind_participant():
    global Participant
    @cassiopeia.type.core.common.inheritdocs
    class Participant(Participant, cassiopeia.type.dto.common.BaseDB):
        __tablename__ = "MatchParticipant"
        championId = sqlalchemy.Column(sqlalchemy.Integer)
        highestAchievedSeasonTier = sqlalchemy.Column(sqlalchemy.String(30))
        masteries = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.Mastery", cascade="all, delete-orphan", passive_deletes=True)
        participantId = sqlalchemy.Column(sqlalchemy.Integer)
        runes = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.Rune", cascade="all, delete-orphan", passive_deletes=True)
        spell1Id = sqlalchemy.Column(sqlalchemy.Integer)
        spell2Id = sqlalchemy.Column(sqlalchemy.Integer)
        stats = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantStats", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        teamId = sqlalchemy.Column(sqlalchemy.Integer)
        timeline = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantTimeline", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        _id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
        _match_id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("MatchDetail.matchId", ondelete="CASCADE"))

def _sa_bind_participant_identity():
    global ParticipantIdentity
    @cassiopeia.type.core.common.inheritdocs
    class ParticipantIdentity(ParticipantIdentity, cassiopeia.type.dto.common.BaseDB):
        __tablename__ = "MatchParticipantIdentity"
        participantId = sqlalchemy.Column(sqlalchemy.Integer)
        player = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.Player", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        _id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
        _match_id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("MatchDetail.matchId", ondelete="CASCADE"))

def _sa_bind_team():
    global Team
    @cassiopeia.type.core.common.inheritdocs
    class Team(Team, cassiopeia.type.dto.common.BaseDB):
        __tablename__ = "MatchTeam"
        bans = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.BannedChampion", cascade="all, delete-orphan", passive_deletes=True)
        baronKills = sqlalchemy.Column(sqlalchemy.Integer)
        dominionVictoryScore = sqlalchemy.Column(sqlalchemy.Integer)
        dragonKills = sqlalchemy.Column(sqlalchemy.Integer)
        firstBaron = sqlalchemy.Column(sqlalchemy.Boolean)
        firstBlood = sqlalchemy.Column(sqlalchemy.Boolean)
        firstDragon = sqlalchemy.Column(sqlalchemy.Boolean)
        firstInhibitor = sqlalchemy.Column(sqlalchemy.Boolean)
        firstTower = sqlalchemy.Column(sqlalchemy.Boolean)
        inhibitorKills = sqlalchemy.Column(sqlalchemy.Integer)
        teamId = sqlalchemy.Column(sqlalchemy.Integer)
        towerKills = sqlalchemy.Column(sqlalchemy.Integer)
        vilemawKills = sqlalchemy.Column(sqlalchemy.Integer)
        winner = sqlalchemy.Column(sqlalchemy.Boolean)
        _id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
        _match_id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("MatchDetail.matchId", ondelete="CASCADE"))

def _sa_bind_timeline():
    global Timeline
    @cassiopeia.type.core.common.inheritdocs
    class Timeline(Timeline, cassiopeia.type.dto.common.BaseDB):
        __tablename__ = "MatchTimeline"
        frameInterval = sqlalchemy.Column(sqlalchemy.Integer)
        frames = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.Frame", cascade="all, delete-orphan", passive_deletes=True)
        _id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
        _match_id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("MatchDetail.matchId", ondelete="CASCADE"))

def _sa_bind_mastery():
    global Mastery
    @cassiopeia.type.core.common.inheritdocs
    class Mastery(Mastery, cassiopeia.type.dto.common.BaseDB):
        __tablename__ = "MatchMastery"
        masteryId = sqlalchemy.Column(sqlalchemy.Integer)
        rank = sqlalchemy.Column(sqlalchemy.Integer)
        _id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
        _participant_id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("MatchParticipant._id", ondelete="CASCADE"))

def _sa_bind_participant_stats():
    global ParticipantStats
    @cassiopeia.type.core.common.inheritdocs
    class ParticipantStats(ParticipantStats, cassiopeia.type.dto.common.BaseDB):
        __tablename__ = "MatchParticipantStats"
        assists = sqlalchemy.Column(sqlalchemy.Integer)
        champLevel = sqlalchemy.Column(sqlalchemy.Integer)
        combatPlayerScore = sqlalchemy.Column(sqlalchemy.Integer)
        deaths = sqlalchemy.Column(sqlalchemy.Integer)
        doubleKills = sqlalchemy.Column(sqlalchemy.Integer)
        firstBloodAssist = sqlalchemy.Column(sqlalchemy.Boolean)
        firstBloodKill = sqlalchemy.Column(sqlalchemy.Boolean)
        firstInhibitorAssist = sqlalchemy.Column(sqlalchemy.Boolean)
        firstInhibitorKill = sqlalchemy.Column(sqlalchemy.Boolean)
        firstTowerAssist = sqlalchemy.Column(sqlalchemy.Boolean)
        firstTowerKill = sqlalchemy.Column(sqlalchemy.Boolean)
        goldEarned = sqlalchemy.Column(sqlalchemy.Integer)
        goldSpent = sqlalchemy.Column(sqlalchemy.Integer)
        inhibitorKills = sqlalchemy.Column(sqlalchemy.Integer)
        item0 = sqlalchemy.Column(sqlalchemy.Integer)
        item1 = sqlalchemy.Column(sqlalchemy.Integer)
        item2 = sqlalchemy.Column(sqlalchemy.Integer)
        item3 = sqlalchemy.Column(sqlalchemy.Integer)
        item4 = sqlalchemy.Column(sqlalchemy.Integer)
        item5 = sqlalchemy.Column(sqlalchemy.Integer)
        item6 = sqlalchemy.Column(sqlalchemy.Integer)
        killingSprees = sqlalchemy.Column(sqlalchemy.Integer)
        kills = sqlalchemy.Column(sqlalchemy.Integer)
        largestCriticalStrike = sqlalchemy.Column(sqlalchemy.Integer)
        largestKillingSpree = sqlalchemy.Column(sqlalchemy.Integer)
        largestMultiKill = sqlalchemy.Column(sqlalchemy.Integer)
        magicDamageDealt = sqlalchemy.Column(sqlalchemy.Integer)
        magicDamageDealtToChampions = sqlalchemy.Column(sqlalchemy.Integer)
        magicDamageTaken = sqlalchemy.Column(sqlalchemy.Integer)
        minionsKilled = sqlalchemy.Column(sqlalchemy.Integer)
        neutralMinionsKilled = sqlalchemy.Column(sqlalchemy.Integer)
        neutralMinionsKilledEnemyJungle = sqlalchemy.Column(sqlalchemy.Integer)
        neutralMinionsKilledTeamJungle = sqlalchemy.Column(sqlalchemy.Integer)
        nodeCapture = sqlalchemy.Column(sqlalchemy.Integer)
        nodeCaptureAssist = sqlalchemy.Column(sqlalchemy.Integer)
        nodeNeutralize = sqlalchemy.Column(sqlalchemy.Integer)
        nodeNeutralizeAssist = sqlalchemy.Column(sqlalchemy.Integer)
        objectivePlayerScore = sqlalchemy.Column(sqlalchemy.Integer)
        pentaKills = sqlalchemy.Column(sqlalchemy.Integer)
        physicalDamageDealt = sqlalchemy.Column(sqlalchemy.Integer)
        physicalDamageDealtToChampions = sqlalchemy.Column(sqlalchemy.Integer)
        physicalDamageTaken = sqlalchemy.Column(sqlalchemy.Integer)
        quadraKills = sqlalchemy.Column(sqlalchemy.Integer)
        sightWardsBoughtInGame = sqlalchemy.Column(sqlalchemy.Integer)
        teamObjective = sqlalchemy.Column(sqlalchemy.Integer)
        totalDamageDealt = sqlalchemy.Column(sqlalchemy.Integer)
        totalDamageDealtToChampions = sqlalchemy.Column(sqlalchemy.Integer)
        totalDamageTaken = sqlalchemy.Column(sqlalchemy.Integer)
        totalHeal = sqlalchemy.Column(sqlalchemy.Integer)
        totalPlayerScore = sqlalchemy.Column(sqlalchemy.Integer)
        totalScoreRank = sqlalchemy.Column(sqlalchemy.Integer)
        totalTimeCrowdControlDealt = sqlalchemy.Column(sqlalchemy.Integer)
        totalUnitsHealed = sqlalchemy.Column(sqlalchemy.Integer)
        towerKills = sqlalchemy.Column(sqlalchemy.Integer)
        tripleKills = sqlalchemy.Column(sqlalchemy.Integer)
        trueDamageDealt = sqlalchemy.Column(sqlalchemy.Integer)
        trueDamageDealtToChampions = sqlalchemy.Column(sqlalchemy.Integer)
        trueDamageTaken = sqlalchemy.Column(sqlalchemy.Integer)
        unrealKills = sqlalchemy.Column(sqlalchemy.Integer)
        visionWardsBoughtInGame = sqlalchemy.Column(sqlalchemy.Integer)
        wardsKilled = sqlalchemy.Column(sqlalchemy.Integer)
        wardsPlaced = sqlalchemy.Column(sqlalchemy.Integer)
        winner = sqlalchemy.Column(sqlalchemy.Boolean)
        _id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
        _participant_id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("MatchParticipant._id", ondelete="CASCADE"))

def _sa_bind_participant_timeline():
    global ParticipantTimeline
    @cassiopeia.type.core.common.inheritdocs
    class ParticipantTimeline(ParticipantTimeline, cassiopeia.type.dto.common.BaseDB):
        __tablename__ = "MatchParticipantTimeline"
        ancientGolemAssistsPerMinCounts = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantTimelineData", primaryjoin="and_(cassiopeia.type.dto.match.ParticipantTimeline._id==cassiopeia.type.dto.match.ParticipantTimelineData._timeline_id, cassiopeia.type.dto.match.ParticipantTimelineData._type=='ancientGolemAssistsPerMinCounts')", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        ancientGolemKillsPerMinCounts = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantTimelineData", primaryjoin="and_(cassiopeia.type.dto.match.ParticipantTimeline._id==cassiopeia.type.dto.match.ParticipantTimelineData._timeline_id, cassiopeia.type.dto.match.ParticipantTimelineData._type=='ancientGolemKillsPerMinCounts')", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        assistedLaneDeathsPerMinDeltas = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantTimelineData", primaryjoin="and_(cassiopeia.type.dto.match.ParticipantTimeline._id==cassiopeia.type.dto.match.ParticipantTimelineData._timeline_id, cassiopeia.type.dto.match.ParticipantTimelineData._type=='assistedLaneDeathsPerMinDeltas')", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        assistedLaneKillsPerMinDeltas = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantTimelineData", primaryjoin="and_(cassiopeia.type.dto.match.ParticipantTimeline._id==cassiopeia.type.dto.match.ParticipantTimelineData._timeline_id, cassiopeia.type.dto.match.ParticipantTimelineData._type=='assistedLaneKillsPerMinDeltas')", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        baronAssistsPerMinCounts = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantTimelineData", primaryjoin="and_(cassiopeia.type.dto.match.ParticipantTimeline._id==cassiopeia.type.dto.match.ParticipantTimelineData._timeline_id, cassiopeia.type.dto.match.ParticipantTimelineData._type=='baronAssistsPerMinCounts')", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        baronKillsPerMinCounts = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantTimelineData", primaryjoin="and_(cassiopeia.type.dto.match.ParticipantTimeline._id==cassiopeia.type.dto.match.ParticipantTimelineData._timeline_id, cassiopeia.type.dto.match.ParticipantTimelineData._type=='baronKillsPerMinCounts')", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        creepsPerMinDeltas = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantTimelineData", primaryjoin="and_(cassiopeia.type.dto.match.ParticipantTimeline._id==cassiopeia.type.dto.match.ParticipantTimelineData._timeline_id, cassiopeia.type.dto.match.ParticipantTimelineData._type=='creepsPerMinDeltas')", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        csDiffPerMinDeltas = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantTimelineData", primaryjoin="and_(cassiopeia.type.dto.match.ParticipantTimeline._id==cassiopeia.type.dto.match.ParticipantTimelineData._timeline_id, cassiopeia.type.dto.match.ParticipantTimelineData._type=='csDiffPerMinDeltas')", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        damageTakenDiffPerMinDeltas = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantTimelineData", primaryjoin="and_(cassiopeia.type.dto.match.ParticipantTimeline._id==cassiopeia.type.dto.match.ParticipantTimelineData._timeline_id, cassiopeia.type.dto.match.ParticipantTimelineData._type=='damageTakenDiffPerMinDeltas')", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        damageTakenPerMinDeltas = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantTimelineData", primaryjoin="and_(cassiopeia.type.dto.match.ParticipantTimeline._id==cassiopeia.type.dto.match.ParticipantTimelineData._timeline_id, cassiopeia.type.dto.match.ParticipantTimelineData._type=='damageTakenPerMinDeltas')", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        dragonAssistsPerMinCounts = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantTimelineData", primaryjoin="and_(cassiopeia.type.dto.match.ParticipantTimeline._id==cassiopeia.type.dto.match.ParticipantTimelineData._timeline_id, cassiopeia.type.dto.match.ParticipantTimelineData._type=='dragonAssistsPerMinCounts')", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        dragonKillsPerMinCounts = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantTimelineData", primaryjoin="and_(cassiopeia.type.dto.match.ParticipantTimeline._id==cassiopeia.type.dto.match.ParticipantTimelineData._timeline_id, cassiopeia.type.dto.match.ParticipantTimelineData._type=='dragonKillsPerMinCounts')", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        elderLizardAssistsPerMinCounts = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantTimelineData", primaryjoin="and_(cassiopeia.type.dto.match.ParticipantTimeline._id==cassiopeia.type.dto.match.ParticipantTimelineData._timeline_id, cassiopeia.type.dto.match.ParticipantTimelineData._type=='elderLizardAssistsPerMinCounts')", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        elderLizardKillsPerMinCounts = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantTimelineData", primaryjoin="and_(cassiopeia.type.dto.match.ParticipantTimeline._id==cassiopeia.type.dto.match.ParticipantTimelineData._timeline_id, cassiopeia.type.dto.match.ParticipantTimelineData._type=='elderLizardKillsPerMinCounts')", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        goldPerMinDeltas = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantTimelineData", primaryjoin="and_(cassiopeia.type.dto.match.ParticipantTimeline._id==cassiopeia.type.dto.match.ParticipantTimelineData._timeline_id, cassiopeia.type.dto.match.ParticipantTimelineData._type=='goldPerMinDeltas')", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        inhibitorAssistsPerMinCounts = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantTimelineData", primaryjoin="and_(cassiopeia.type.dto.match.ParticipantTimeline._id==cassiopeia.type.dto.match.ParticipantTimelineData._timeline_id, cassiopeia.type.dto.match.ParticipantTimelineData._type=='inhibitorAssistsPerMinCounts')", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        inhibitorKillsPerMinCounts = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantTimelineData", primaryjoin="and_(cassiopeia.type.dto.match.ParticipantTimeline._id==cassiopeia.type.dto.match.ParticipantTimelineData._timeline_id, cassiopeia.type.dto.match.ParticipantTimelineData._type=='inhibitorKillsPerMinCounts')", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        lane = sqlalchemy.Column(sqlalchemy.String(30))
        role = sqlalchemy.Column(sqlalchemy.String(30))
        towerAssistsPerMinCounts = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantTimelineData", primaryjoin="and_(cassiopeia.type.dto.match.ParticipantTimeline._id==cassiopeia.type.dto.match.ParticipantTimelineData._timeline_id, cassiopeia.type.dto.match.ParticipantTimelineData._type=='towerAssistsPerMinCounts')", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        towerKillsPerMinCounts = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantTimelineData", primaryjoin="and_(cassiopeia.type.dto.match.ParticipantTimeline._id==cassiopeia.type.dto.match.ParticipantTimelineData._timeline_id, cassiopeia.type.dto.match.ParticipantTimelineData._type=='towerKillsPerMinCounts')", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        towerKillsPerMinDeltas = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantTimelineData", primaryjoin="and_(cassiopeia.type.dto.match.ParticipantTimeline._id==cassiopeia.type.dto.match.ParticipantTimelineData._timeline_id, cassiopeia.type.dto.match.ParticipantTimelineData._type=='towerKillsPerMinDeltas')", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        vilemawAssistsPerMinCounts = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantTimelineData", primaryjoin="and_(cassiopeia.type.dto.match.ParticipantTimeline._id==cassiopeia.type.dto.match.ParticipantTimelineData._timeline_id, cassiopeia.type.dto.match.ParticipantTimelineData._type=='vilemawAssistsPerMinCounts')", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        vilemawKillsPerMinCounts = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantTimelineData", primaryjoin="and_(cassiopeia.type.dto.match.ParticipantTimeline._id==cassiopeia.type.dto.match.ParticipantTimelineData._timeline_id, cassiopeia.type.dto.match.ParticipantTimelineData._type=='vilemawKillsPerMinCounts')", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        wardsPerMinDeltas = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantTimelineData", primaryjoin="and_(cassiopeia.type.dto.match.ParticipantTimeline._id==cassiopeia.type.dto.match.ParticipantTimelineData._timeline_id, cassiopeia.type.dto.match.ParticipantTimelineData._type=='wardsPerMinDeltas')", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        xpDiffPerMinDeltas = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantTimelineData", primaryjoin="and_(cassiopeia.type.dto.match.ParticipantTimeline._id==cassiopeia.type.dto.match.ParticipantTimelineData._timeline_id, cassiopeia.type.dto.match.ParticipantTimelineData._type=='xpDiffPerMinDeltas')", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        xpPerMinDeltas = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantTimelineData", primaryjoin="and_(cassiopeia.type.dto.match.ParticipantTimeline._id==cassiopeia.type.dto.match.ParticipantTimelineData._timeline_id, cassiopeia.type.dto.match.ParticipantTimelineData._type=='xpPerMinDeltas')", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        _id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
        _participant_id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("MatchParticipant._id", ondelete="CASCADE"))

def _sa_bind_rune():
    global Rune
    @cassiopeia.type.core.common.inheritdocs
    class Rune(Rune, cassiopeia.type.dto.common.BaseDB):
        __tablename__ = "MatchRune"
        rank = sqlalchemy.Column(sqlalchemy.Integer)
        runeId = sqlalchemy.Column(sqlalchemy.Integer)
        _id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
        _participant_id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("MatchParticipant._id", ondelete="CASCADE"))

def _sa_bind_player():
    global Player
    @cassiopeia.type.core.common.inheritdocs
    class Player(Player, cassiopeia.type.dto.common.BaseDB):
        __tablename__ = "MatchPlayer"
        matchHistoryUri = sqlalchemy.Column(sqlalchemy.String(50))
        profileIcon = sqlalchemy.Column(sqlalchemy.Integer)
        summonerId = sqlalchemy.Column(sqlalchemy.Integer)
        summonerName = sqlalchemy.Column(sqlalchemy.String(30))
        _id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
        _participant_id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("MatchParticipantIdentity._id", ondelete="CASCADE"))

def _sa_bind_banned_champion():
    global BannedChampion
    @cassiopeia.type.core.common.inheritdocs
    class BannedChampion(BannedChampion, cassiopeia.type.dto.common.BaseDB):
        __tablename__ = "MatchBannedChampion"
        championId = sqlalchemy.Column(sqlalchemy.Integer)
        pickTurn = sqlalchemy.Column(sqlalchemy.Integer)
        _id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
        _team_id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("MatchTeam._id", ondelete="CASCADE"))

def _sa_bind_frame():
    global Frame
    @cassiopeia.type.core.common.inheritdocs
    class Frame(Frame, cassiopeia.type.dto.common.BaseDB):
        __tablename__ = "MatchFrame"
        events = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.Event", cascade="all, delete-orphan", passive_deletes=True)
        participantFrames = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.ParticipantFrame", collection_class=sqlalchemy.orm.collections.mapped_collection(lambda p: str(p.participantId)), cascade="all, delete-orphan", passive_deletes=True) # OR I HAVE NO IDEA
        timestamp = sqlalchemy.Column(sqlalchemy.Integer)
        _id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
        _timeline_id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("MatchTimeline._id", ondelete="CASCADE"))

def _sa_bind_participant_timeline_data():
    global ParticipantTimelineData
    @cassiopeia.type.core.common.inheritdocs
    class ParticipantTimelineData(ParticipantTimelineData, cassiopeia.type.dto.common.BaseDB):
        __tablename__ = "MatchParticipantTimelineData"
        tenToTwenty = sqlalchemy.Column(sqlalchemy.Float)
        thirtyToEnd = sqlalchemy.Column(sqlalchemy.Float)
        twentyToThirty = sqlalchemy.Column(sqlalchemy.Float)
        zeroToTen = sqlalchemy.Column(sqlalchemy.Float)
        _type = sqlalchemy.Column(sqlalchemy.String(50))
        _id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
        _timeline_id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("MatchParticipantTimeline._id", ondelete="CASCADE"))

def _sa_bind_event():
    global Event
    @cassiopeia.type.core.common.inheritdocs
    class Event(Event, cassiopeia.type.dto.common.BaseDB):
        __tablename__ = "MatchEvent"
        ascendedType = sqlalchemy.Column(sqlalchemy.String(30))
        assistingParticipantIds = sqlalchemy.Column(cassiopeia.type.dto.common.JSONEncoded)
        buildingType = sqlalchemy.Column(sqlalchemy.String(30))
        creatorId = sqlalchemy.Column(sqlalchemy.Integer)
        eventType = sqlalchemy.Column(sqlalchemy.String(30))
        itemAfter = sqlalchemy.Column(sqlalchemy.Integer)
        itemBefore = sqlalchemy.Column(sqlalchemy.Integer)
        itemId = sqlalchemy.Column(sqlalchemy.Integer)
        killerId = sqlalchemy.Column(sqlalchemy.Integer)
        laneType = sqlalchemy.Column(sqlalchemy.String(30))
        levelUpType = sqlalchemy.Column(sqlalchemy.String(30))
        monsterType = sqlalchemy.Column(sqlalchemy.String(30))
        participantId = sqlalchemy.Column(sqlalchemy.Integer)
        pointCaptured = sqlalchemy.Column(sqlalchemy.String(30))
        position = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.Position", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        skillSlot = sqlalchemy.Column(sqlalchemy.Integer)
        teamId = sqlalchemy.Column(sqlalchemy.Integer)
        timestamp = sqlalchemy.Column(sqlalchemy.Integer)
        towerType = sqlalchemy.Column(sqlalchemy.String(30))
        victimId = sqlalchemy.Column(sqlalchemy.Integer)
        wardType = sqlalchemy.Column(sqlalchemy.String(30))
        _id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
        _frame_id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("MatchFrame._id", ondelete="CASCADE"))

def _sa_bind_participant_frame():
    global ParticipantFrame
    @cassiopeia.type.core.common.inheritdocs
    class ParticipantFrame(ParticipantFrame, cassiopeia.type.dto.common.BaseDB):
        __tablename__ = "MatchParticipantFrame"
        currentGold = sqlalchemy.Column(sqlalchemy.Integer)
        dominionScore = sqlalchemy.Column(sqlalchemy.Integer)
        jungleMinionsKilled = sqlalchemy.Column(sqlalchemy.Integer)
        level = sqlalchemy.Column(sqlalchemy.Integer)
        minionsKilled = sqlalchemy.Column(sqlalchemy.Integer)
        participantId = sqlalchemy.Column(sqlalchemy.Integer)
        position = sqlalchemy.orm.relationship("cassiopeia.type.dto.match.Position", uselist=False, cascade="all, delete-orphan", passive_deletes=True)
        teamScore = sqlalchemy.Column(sqlalchemy.Integer)
        totalGold = sqlalchemy.Column(sqlalchemy.Integer)
        xp = sqlalchemy.Column(sqlalchemy.Integer)
        _id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
        _frame_id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("MatchFrame._id", ondelete="CASCADE"))

def _sa_bind_position():
    global Position
    @cassiopeia.type.core.common.inheritdocs
    class Position(Position, cassiopeia.type.dto.common.BaseDB):
        __tablename__ = "MatchPosition"
        x = sqlalchemy.Column(sqlalchemy.Integer)
        y = sqlalchemy.Column(sqlalchemy.Integer)
        _id = sqlalchemy.Column(sqlalchemy.Integer, primary_key=True)
        _event_id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("MatchEvent._id", ondelete="CASCADE"))
        _frame_id = sqlalchemy.Column(sqlalchemy.Integer, sqlalchemy.ForeignKey("MatchParticipantFrame._id", ondelete="CASCADE"))

def _sa_bind_all():
    _sa_bind_match_detail()
    _sa_bind_participant()
    _sa_bind_participant_identity()
    _sa_bind_team()
    _sa_bind_timeline()
    _sa_bind_mastery()
    _sa_bind_participant_stats()
    _sa_bind_participant_timeline()
    _sa_bind_rune()
    _sa_bind_player()
    _sa_bind_banned_champion()
    _sa_bind_frame()
    _sa_bind_participant_timeline_data()
    _sa_bind_event()
    _sa_bind_participant_frame()
    _sa_bind_position()