Top Level Namespace

Defined Under Namespace

Modules: Copycats, Lottery Classes: CreateDb, Gene, GenesReport, Genome, GenomeMixTables, GenomeTables, KittyReport, MixReport, TraitsReport

Constant Summary collapse

TRAITS =

ordered by gene position (0,1,3.4,5,… etc.)

12 traits (4 genes each)
{
  body: {
    genes: '0-3',
    name:  'Fur',  code: 'FU',
    kai: {
    '1' => 'savannah',
    '2' => 'selkirk',
    '3' => 'chantilly',
    '4' => 'birman',
    '5' => 'koladiviya',
    '6' => 'bobtail',
    '7' => 'manul',
    '8' => 'pixiebob',
    '9' => 'siberian',
    'a' => 'cymric',
    'b' => 'chartreux',
    'c' => 'himalayan',
    'd' => 'munchkin',
    'e' => 'sphynx',
    'f' => 'ragamuffin',
    'g' => 'ragdoll',
    'h' => 'norwegianforest',
    'i' => 'mekong',
    'j' => 'highlander',
    'k' => 'balinese',
    'm' => 'lynx',
    'n' => 'mainecoon',
    'o' => 'laperm',
    'p' => 'persian',
    'q' => 'fox',
    'r' => 'kurilian',
    's' => 'toyger',
    't' => 'manx',
    'u' => 'lykoi',
    'v' => 'burmilla',
    'w' => 'liger',
    'x' => ''
    }
  },
  pattern: {
    genes: '4-7',
    name: 'Pattern', code: 'PA',
    kai: {
    '1' => 'vigilante',
    '2' => 'tiger',
    '3' => 'rascal',
    '4' => 'ganado',
    '5' => 'leopard',
    '6' => 'camo',
    '7' => 'rorschach',
    '8' => 'spangled',
    '9' => 'calicool',
    'a' => 'luckystripe',
    'b' => 'amur',
    'c' => 'jaguar',
    'd' => 'spock',
    'e' => 'mittens',
    'f' => 'totesbasic',  ## use totesbasic_f - why? why not?
    'g' => 'totesbasic',  ## use totesbasic_g
    'h' => 'splat',
    'i' => 'thunderstruck',
    'j' => 'dippedcone',
    'k' => 'highsociety',
    'm' => 'tigerpunk',
    'n' => 'henna',
    'o' => 'arcreactor',
    'p' => 'totesbasic',  ## use totesbasic_p
    'q' => 'scorpius',
    'r' => 'razzledazzle',
    's' => 'hotrod',
    't' => 'allyouneed',
    'u' => 'avatar',
    'v' => 'gyre',
    'w' => 'moonrise',
    'x' => ''
    }
  },
  coloreyes: {
    genes: '8-11',
    name:  'Eye Color', code: 'EC',
    kai: {
    '1' => 'thundergrey',
    '2' => 'gold',
    '3' => 'topaz',
    '4' => 'mintgreen',
    '5' => 'isotope',
    '6' => 'sizzurp',
    '7' => 'chestnut',
    '8' => 'strawberry',
    '9' => 'sapphire',
    'a' => 'forgetmenot',
    'b' => 'dahlia',
    'c' => 'coralsunrise',
    'd' => 'olive',
    'e' => 'doridnudibranch',
    'f' => 'parakeet',
    'g' => 'cyan',
    'h' => 'pumpkin',
    'i' => 'limegreen',
    'j' => 'bridesmaid',
    'k' => 'bubblegum',
    'm' => 'twilightsparkle',
    'n' => 'palejade',
    'o' => 'pinefresh',
    'p' => 'eclipse',
    'q' => 'babypuke',
    'r' => 'downbythebay',
    's' => 'autumnmoon',
    't' => 'oasis',
    'u' => 'gemini',
    'v' => 'dioscuri',
    'w' => 'kaleidoscope',
    'x' => ''
    }
  },
  eyes: {
    genes: '12-15',
    name: 'Eye Shape', code: 'ES',     ##  eye type
    kai: {
    '1' => 'swarley',
    '2' => 'wonky',
    '3' => 'serpent',
    '4' => 'googly',
    '5' => 'otaku',
    '6' => 'simple',
    '7' => 'crazy',
    '8' => 'thicccbrowz',
    '9' => 'caffeine',
    'a' => 'wowza',
    'b' => 'baddate',
    'c' => 'asif',
    'd' => 'chronic',
    'e' => 'slyboots',
    'f' => 'wiley',
    'g' => 'stunned',
    'h' => 'chameleon',
    'i' => 'alien',
    'j' => 'fabulous',
    'k' => 'raisedbrow',
    'm' => 'tendertears',
    'n' => 'hacker',
    'o' => 'sass',
    'p' => 'sweetmeloncakes',
    'q' => 'oceanid',
    'r' => 'wingtips',
    's' => 'firedup',
    't' => 'buzzed',
    'u' => 'bornwithit',
    'v' => 'candyshoppe',
    'w' => 'drama',
    'x' => ''
    }
  },
  color1: {
    genes: '16-19',
    name: 'Base Color', code: 'BC',   ##  colorprimary / body color
    kai: {
    '1' => 'shadowgrey',
    '2' => 'salmon',
    '3' => 'meowgarine',
    '4' => 'orangesoda',
    '5' => 'cottoncandy',
    '6' => 'mauveover',
    '7' => 'aquamarine',
    '8' => 'nachocheez',
    '9' => 'harbourfog',
    'a' => 'cinderella',
    'b' => 'greymatter',
    'c' => 'tundra',
    'd' => 'brownies',
    'e' => 'dragonfruit',
    'f' => 'hintomint',
    'g' => 'bananacream',
    'h' => 'cloudwhite',
    'i' => 'cornflower',
    'j' => 'oldlace',
    'k' => 'koala',
    'm' => 'lavender',
    'n' => 'glacier',
    'o' => 'redvelvet',
    'p' => 'verdigris',
    'q' => 'icicle',
    'r' => 'onyx',
    's' => 'hyacinth',
    't' => 'martian',
    'u' => 'hotcocoa',
    'v' => 'shamrock',
    'w' => 'firstblush',
    'x' => ''
    }
  },
  color2: {
    genes: '20-23',
    name:  'Highlight Color', code: 'HC',    ## colorsecondary / sec color / pattern color
    kai: {
    '1' => 'cyborg',
    '2' => 'springcrocus',
    '3' => 'egyptiankohl',
    '4' => 'poisonberry',
    '5' => 'lilac',
    '6' => 'apricot',
    '7' => 'royalpurple',
    '8' => 'padparadscha',
    '9' => 'swampgreen',
    'a' => 'violet',
    'b' => 'scarlet',
    'c' => 'barkbrown',
    'd' => 'coffee',
    'e' => 'lemonade',
    'f' => 'chocolate',
    'g' => 'butterscotch',
    'h' => 'ooze',
    'i' => 'safetyvest',
    'j' => 'turtleback',
    'k' => 'rosequartz',
    'm' => 'wolfgrey',
    'n' => 'cerulian',
    'o' => 'skyblue',
    'p' => 'garnet',
    'q' => 'peppermint',
    'r' => 'universe',
    's' => 'royalblue',
    't' => 'mertail',
    'u' => 'inflatablepool',
    'v' => 'pearl',
    'w' => 'prairierose',
    'x' => ''
    }
  },
  color3: {
    genes: '24-27',
    name: 'Accent Color', code: 'AC',   ## colortertiary
    kai: {
    '1' => 'belleblue',
    '2' => 'sandalwood',
    '3' => 'peach',
    '4' => 'icy',
    '5' => 'granitegrey',
    '6' => 'cashewmilk',
    '7' => 'kittencream',
    '8' => 'emeraldgreen',
    '9' => 'kalahari',
    'a' => 'shale',
    'b' => 'purplehaze',
    'c' => 'hanauma',
    'd' => 'azaleablush',
    'e' => 'missmuffett',
    'f' => 'morningglory',
    'g' => 'frosting',
    'h' => 'daffodil',
    'i' => 'flamingo',
    'j' => 'buttercup',
    'k' => 'bloodred',
    'm' => 'atlantis',
    'n' => 'summerbonnet',
    'o' => 'periwinkle',
    'p' => 'patrickstarfish',
    'q' => 'seafoam',
    'r' => 'cobalt',
    's' => 'mallowflower',
    't' => 'mintmacaron',
    'u' => 'sully',
    'v' => 'fallspice',
    'w' => 'dreamboat',
    'x' => ''
    }
  },
  wild: {
    genes: '28-31',
    name: 'Wild', code: 'WE',
    kai: {
    'h' => 'littlefoot',
    'i' => 'elk',
    'j' => 'ducky',
    'k' => 'trioculus',
    'm' => 'daemonwings',
    'n' => 'featherbrain',
    'o' => 'flapflap',
    'p' => 'daemonhorns',
    'q' => 'dragontail',
    'r' => 'aflutter',
    's' => 'foghornpawhorn',
    't' => 'unicorn',
    'u' => 'dragonwings',
    'v' => 'alicorn',
    'w' => 'wyrm',
    'x' => ''
    }
  },
  mouth: {
    genes: '32-35',
    name:  'Mouth', code: 'MO',
    kai: {
    '1' => 'whixtensions',
    '2' => 'wasntme',
    '3' => 'wuvme',
    '4' => 'gerbil',
    '5' => 'confuzzled',
    '6' => 'impish',
    '7' => 'belch',
    '8' => 'rollercoaster',
    '9' => 'beard',
    'a' => 'pouty',
    'b' => 'saycheese',
    'c' => 'grim',
    'd' => 'fangtastic',
    'e' => 'moue',
    'f' => 'happygokitty',
    'g' => 'soserious',
    'h' => 'cheeky',
    'i' => 'starstruck',
    'j' => 'samwise',
    'k' => 'ruhroh',
    'm' => 'dali',
    'n' => 'grimace',
    'o' => 'majestic',
    'p' => 'tongue',
    'q' => 'yokel',
    'r' => 'topoftheworld',
    's' => 'neckbeard',
    't' => 'satiated',
    'u' => 'walrus',
    'v' => 'struck',
    'w' => 'delite',
    'x' => ''
   }
  },
  environment: {
      genes: '36-39',
      name: 'Environment', code: 'EN',
      kai: {
        'h' => 'salty',
        'i' => 'dune',
        'j' => 'juju',
        'k' => 'tinybox',
        'm' => 'myparade',
        'n' => 'finalfrontier',
        'o' => 'metime',
        'p' => 'drift',
        'q' => 'secretgarden',
        'r' => 'frozen',
        's' => 'roadtogold',
        't' => 'jacked',
        'u' => 'floorislava',
        'v' => 'prism',
        'w' => 'junglebook',
        'x' => ''
      }
  },
  secret: {
      genes: '40-43',
      name: 'Secret Y Gene', code: 'SE',   ## todo: change to Y Gene or Y (see https://guide.cryptokitties.co/guide/cat-features/genes)
      kai: { }
      ## use alpha_1, alpha_2, ... - why? why not?
      ## use beta_1, beta_2, ... - why? why not?
      ## use gamma_1, gamma_2, ... - why? why not?
  },
  prestige: {
      genes: '44-47',
      name: 'Purrstige', code: 'PU',
      kai: { }
      ##  prune, furball, duckduckcat, or thatsawrap - more like fancies (not really traits)
  }
}
TRAITS_BY_NAME =

build “reverse” lookup tables

{}
TRAITS_BY_CODE =

e.g. savannah, selkirk, chantilly, …

{}
TIER =

Tier 0 (Base) (1-g)

Tier 1 (Mewtation I)    (h-p)
Tier 2 (Mewtation II)   (q-t)
Tier 3 (Mewtation III)  (u,v)
Tier 4 (Mewtation IIII) (w)
{    ## todo/fix: use an algo to calculate - why? why not?
  '1' => 0,
  '2' => 0,
  '3' => 0,
  '4' => 0,
  '5' => 0,
  '6' => 0,
  '7' => 0,
  '8' => 0,
  '9' => 0,
  'a' => 0,
  'b' => 0,
  'c' => 0,
  'd' => 0,
  'e' => 0,
  'f' => 0,
  'g' => 0,
  'h' => 1,
  'i' => 1,
  'j' => 1,
  'k' => 1,
  'm' => 1,
  'n' => 1,
  'o' => 1,
  'p' => 1,
  'q' => 2,
  'r' => 2,
  's' => 2,
  't' => 2,
  'u' => 3,
  'v' => 3,
  'w' => 4,
  'x' => nil
}
MUTATION_LEVEL =

(quick ‘n’ dirty) kai to mutation/mewtation level (I,II,III,IIII)

{
  '1' => '',
  '2' => '',
  '3' => '',
  '4' => '',
  '5' => '',
  '6' => '',
  '7' => '',
  '8' => '',
  '9' => '',
  'a' => '',
  'b' => '',
  'c' => '',
  'd' => '',
  'e' => '',
  'f' => '',
  'g' => '',
  'h' => 'I',
  'i' => 'I',
  'j' => 'I',
  'k' => 'I',
  'm' => 'I',
  'n' => 'I',
  'o' => 'I',
  'p' => 'I',
  'q' => 'II',
  'r' => 'II',
  's' => 'II',
  't' => 'II',
  'u' => 'III',
  'v' => 'III',
  'w' => 'IIII',
  'x' => ''
}
MEWTATION_LEVEL =

add alias

MUTATION_LEVEL
MUTATION_PAIR =
{
  '1' => '',   ## todo: use nil for "" - why? why not?
  '2' => '',
  '3' => '',
  '4' => '',
  '5' => '',
  '6' => '',
  '7' => '',
  '8' => '',
  '9' => '',
  'a' => '',
  'b' => '',
  'c' => '',
  'd' => '',
  'e' => '',
  'f' => '',
  'g' => '',
  'h' => '1+2',
  'i' => '3+4',
  'j' => '5+6',
  'k' => '7+8',
  'm' => '9+a',
  'n' => 'b+c',
  'o' => 'd+e',
  'p' => 'f+g',
  'q' => 'h+i',
  'r' => 'j+k',
  's' => 'm+n',
  't' => 'o+p',
  'u' => 'q+r',
  'v' => 's+t',
  'w' => 'u+v',
  'x' => ''
}
MEWTATION_PAIR =

add alias

MUTATION_PAIR
FANCIES =
{
  ## 2018
  ## November
  draco:                { name: 'Draco',        date: '2018-11-30', time: { end: '2018-12-07' },
                          traits: ['toyger', 'martian', 'peppermint', 'dragonwings', 'SE03']},
  dracothemagnificent:  { name: 'Draco The Magnificent', date: '2018-11-27', limit: 12, exclusive: true, ids:	(270..281).to_a },
  bugcatv2:             { name: 'Bug Cat V2',            date: '2018-11-27', limit: 20, exclusive: true, ids: (167..186).to_a, desc: 'Bug Bounty II (Offers Contract) Kitty' },
  dracojunior: { name: 'Draco Junior', date: '2018-11-26', time: { end: '2018-12-07' },
                 traits: ['lynx', 'verdigris', 'dragontail', 'SE03']},
  dreggo:      { name: 'Dreggo',       date: '2018-11-21', time: { end: '2018-12-07' },
                 traits: ['siberian', 'bananacream', 'SE03']},
  pickles:     { name: 'Pickles',      date: '2018-11-14',  limit: 303,
                 traits: ['lynx', 'martian', 'highsociety', 'emeraldgreen']},
  lilbub:      { name: 'Lil Bub Ub Bub (BUB)',   date: '2018-11-13',  limit: 42, special: true },  ## for search use specialedition:

  lilbubthemagicalspacecat: { name: 'Lil Bub Ub Bub (BUB) The Magical Space Cat', date: '2018-11-13', limit: 3, exclusive: true, ids: [266,267,268] },

  ## October
  thatsawrap:  { name: 'Thatsawrap', date: '2018-10-21', limit:	615, time: { start: '2018-10-20', end: '2018-11-06' }, prestige: true,
                  traits: ['bobtail','WE00','PU28']},
  duckduckcat: { name: 'Duckduckcat', date: '2018-10-19', limit: 1249, time: { start: '2018-10-20', end: '2018-11-15' }, prestige: true,
                   traits: ['neckbeard',['PU24','PU25','PU26']]},  ##  Purrstige: PU24 / PU25 / PU26

  dukecat:       { name: 'Dukecat',       date: '2018-10-18', limit: 1366,
                   traits: ['cymric', 'periwinkle', 'simple', 'tongue']},
  sheilapurren:  { name: 'Sheila Purren', date: '2018-10-04', limit: 1971, desc: 'Sheila Warren Kitty-fied - Head of Blockchain and Distributed Ledger Technology at the World Economic Forum (WEF)',
                   traits: ['mauveover', 'icy', 'wingtips', 'fangtastic']},

  ## September
  pawzilla: { name: 'Pawzilla', date: '2018-09-22', limit: 1185,
              traits: ['jaguar', 'universe', 'atlantis', 'littlefoot']},
  prune:   { name: 'Prune', date: '2018-09-19', limit: 921, time: { start: '2018-09-18', end: '2018-09-30' }, prestige: true,
            traits: ['norwegianforest', 'totesbasic', 'PU25']},     ## todo/fix: check totesbasic - three genes!!! - check which one PA15?
  furball:  { name: 'Furball', date: '2018-09-19', limit: 998, time: { start: '2018-09-19', end: '2018-09-30' }, prestige: true,
              traits: ['norwegianforest', 'totesbasic', 'PU26']},   ## todo/fix: check totesbasic - three genes!!! - check which one PA15?
  vulcat:   { name: 'Vulcat',   date: '2018-09-12', limit: 1, exclusive: true, ids: [1000000], desc: '1 000 000th Kitty' },
  meowstro: { name: 'Meowstro', date: '2018-09-09', limit: 1698,
              traits: ['onyx', 'wowza', 'eclipse']},
  atlas:    { name: 'Atlas',    date: '2018-09-07', limit: 998,
              traits: ['highlander', 'kittencream', 'swarley', 'topoftheworld']},

  ## August
  vulcant:        { name: 'Vulcant',        date: '2018-08-31', limit: 20, exclusive: true, ids: [932914,937360,938299,946526,948925,949058,950617,952280,952981,956374,956908,958570,964205,967234,983046,984451,990713,992861,995745,997469] },
  purrity:        { name: 'Purrity',        date: '2018-08-23', limit: 5984,
                    traits: ['selkirk', 'chronic', 'cloudwhite', 'cheeky']},
  rabbidkitty:    { name: 'Rabbid Kitty',   date: '2018-08-23', limit: 6, exclusive: true, ids: (260..265).to_a, desc: 'Ubisoft Blockchain Heroes Hackathon' },
  squiddlesworth: { name: 'Squiddlesworth', date: '2018-08-16', limit: 1510, desc: 'Lava Squid Cat',
                     traits: ['sphynx', 'redvelvet', 'patrickstarfish', 'dragontail']},

  ## July
  purrspero:      { name: 'Purrspero',   date: '2018-07-27', limit: 4448,
                    traits: ['dippedcone', 'googly', 'royalpurple', 'beard']},
  catbury:        { name: 'Catbury',     date: '2018-07-25', limit: 76,
                     traits: ['ragdoll', 'crazy', 'chocolate', 'mintmacaron', 'yokel', 'WE02']},
  honu:           { name: 'Honu',        date: '2018-07-20', limit: 1, exclusive: true, ids: [251], desc: 'Kitties for Good - Save Turtle Habitats' },
  victoire:       { name: 'Victoire',    date: '2018-07-18', limit: 1, exclusive: true, ids: [402], desc: 'France Football World Cup Champion' },
  lulu:           { name: 'Lulu',        date: '2018-07-13', limit: 999,
                    traits: ['cyan', 'verdigris', 'turtleback', 'salty']},
  boot:           { name: 'Boot',        date: '2018-07-05', limit: 1440,  desc: 'Football World Cup',
                    traits: ['ganado', 'wiley', 'cerulian', 'rollercoaster'],
                    variants: {
                      belgium: { name: 'Belgium', limit: 97,   traits: [['orangesoda','onyx']]},                    ## Base Color: Orangesoda / Onyx
                      brazil:  { name: 'Brazil',  limit: 195,  traits: [['hintomint','bananacream','verdigris']]},  ## Base Color: Hintomint / Bananacream / Verdigris
                      croatia: { name: 'Croatia', limit: 253,  traits: [['cottoncandy','mauveover','oldlace']]},    ## Base Color: Cottoncandy / Mauveover / Oldlace
                      england: { name: 'England', limit: 168,  traits: [['greymatter','martian']]},                 ## Base Color: Greymatter / Martian
                      france:  { name: 'France',  limit: 317,  traits: [['harbourfog','cinderella','lavender']]},   ## Base Color: Harbourfog / Cinderella / Lavender
                      russia:  { name: 'Russia',  limit: 94,   traits: [['shadowgrey','salmon','cloudwhite']]},     ## Base Color: Shadowgrey / Salmon/ Cloudwhite
                      sweden:  { name: 'Sweden',  limit: 123,  traits: [['brownies','dragonfruit','redvelvet']]},   ## Base Color: Brownies / Dragonfruit / Redvelvet
                      uruguay: { name: 'Uruguay', limit: 193,  traits: [['aquamarine','nachocheez','koala']]},      ## Base Color: Aquamarine / Nachocheez / Koala
                    },
                  },
  ## note: boot - different variants for world cup teams
  ##  Although there are 8 unique Fancies, they're actually each a variant on the same Fancy - Boot.
  ##  Their colours are different, and you can collect all 8 as a set

  ## June
  raspoutine:    { name: 'Raspoutine',  date: '2018-06-28', limit: 1867,
                    traits: ['buzzed', 'nachocheez', 'sandalwood', 'belch']},
  furlin:        { name: 'Furlin',      date: '2018-06-26', limit: 52, exclusive: true, ids: (115..126).to_a + (128..166).to_a },
  kittypride:    { name: 'Kitty Pride', date: '2018-06-21', limit: 1316,
                    traits: ['fabulous','cinderella','garnet']},
  furrmingo:     { name: 'Furrmingo',   date: '2018-06-14', limit: 333,
                    traits: ['bobtail', 'egyptiankohl', 'flamingo', 'whixtensions']},

  ## May
  page:              { name: 'Page',              date: '2018-05-31',  limit: 50_000,
                       traits: ['rascal', 'peach', 'wasntme' ]},
  "schrödingerscat": { name: "Schrödinger's Cat", date: '2018-05-20',  limit: 73,
                        traits: ['forgetmenot','tinybox','PU20','SE25']},
  chatplongeur:      { name: 'Chat Plongeur',     date: '2018-05-19',  limit: 1910,
                        traits: ['aquamarine', 'skyblue', 'seafoam']},
  docpurr:             { name: 'Doc Purr',         date: '2018-05-16',  limit: 250,
                          traits: ['persian','spock','raisedbrow','violet','tongue']},
  celestialcyberdimension: { name: 'Celestial Cyber Dimension', date: '2018-05-12', limit: 1, exclusive: true, ids: [127] },
  swish:               { name: 'Swish', date: '2018-05-08', limit: 2880,
                          traits: ['norwegianforest', 'luckystripes', 'thicccbrowz', 'orangesoda']},

  ## April
  flutterbee:  { name: 'Flutterbee', date: '2018-04-28', limit: 275,
                 traits: ['cloudwhite','jaguar','lemonade','azaleablush','WE14']},
  vernon:      { name: 'Vernon',     date: '2018-04-16', limit: 320, desc: 'Spring Equinox Kitty',
                  traits: ['amur','fabulous','cottoncandy','springcrocus','belleblue','soserious']},  ## first, see https://www.cryptokitties.co/kitty/696398

  ## March
  berry:           { name: 'Berry',   date: '2018-03-16', limit: 200,
                     traits: ['dragonfruit','thunderstruck','emeraldgreen','apricot','simple']},
  pussforprogress: { name: 'Puss For Progress', date: '2018-03-08', limit: 1920, desc: "Women's Day",
                     traits: ['himalayan','peach','safetyvest','gerbil']},
  fortunecat:      { name: 'Fortune Cat', name_cn: '红包喵', date: '2018-03-08', limit: 888,
                      traits: ['harbourfog','calicool','swampgreen','sapphire','beard']},  ## todo: check date for china launch specials!!!
  goldendragoncat: { name: 'Golden Dragon Cat', name_cn: '帝龙喵', date: '2018-03-08', limit: 1, exclusive: true, ids: [888], desc: 'China Launch' }, ## todo: check date for china launch specials!!!
  goldendogcat:    { name: 'Golden Dog Cat', name_cn: '旺财汪', date: '2018-03-08', limit: 11, exclusive: true, ids: [1802,1803,1805,1806,1808,1809,1812,1816]+(1825..1828).to_a, desc: 'China Launch' },  ## todo: check date for china launch specials!!!
  liondance:    { name: 'Lion Dance', name_cn: '咚咚锵', date: '2018-03-07', limit: 888, overflow: 1,
                    traits: ['manx','royalblue','googly','starstruck']},
  dogcat:       { name: 'Dog Cat',    name_cn: '汪星爷', date: '2018-03-02', limit: 88, desc: 'Year of the Dog (Greater China)',
                   traits: ['tigerpunk','periwinkle','barkbrown','sweetmeloncakes','yokel']},
  knightkitty:  { name: 'Knight Kitty',  date: '2018-03-01',  limit: 11, exclusive: true, ids: (104..114).to_a },

  ## February
  tabby:           { name: 'Tabby',           date: '2018-02-26', limit: 250,
                      traits: ['ragamuffin','morningglory','otaku','cheeky']},
  yuricatsuki:     { name: 'Yuri Catsuki',    date: '2018-02-20', limit: 250,  desc: 'Figure Scating Kitty - Winter Olympics (Korea)',
                       traits: ['cymric','tiger','neckbeard','elk']},
  misterpurrfect:  { name: 'Mister Purrfect', date: '2018-02-14', limit: 1000, desc: "Valentine's Day",
                        traits: ['chocolate','baddate','strawberry','wuvme']},
  earnie:          { name: 'Earnie',          date: '2018-02-13', limit: 500,  desc: 'Earn.com - Golden Kitty Award (Product Hunt)',
                        traits: ['birman','orangesoda','hotrod','grim']},
  cathena:         { name: 'Cathena',         date: '2018-02-06', limit: 1,  exclusive: true, ids: [500000], desc: '500 000th Kitty' },

  ## January
  'momo-chan':     { name: 'Momo-chan',       date: '2018-01-31',  limit: 500, desc: 'Ninja Kitty',
                       traits: ['onyx','henna','bloodred','wolfgrey','sass']},
  negato:          { name: 'Negato',          date: '2018-01-29',  limit: 500, desc: 'Ninja Kitty',
                       traits: ['onyx','henna','wolfgrey','slyboots']},
  stitches:        { name: 'Stitches',         date: '2018-01-10',  limit: 500, desc: 'Zombie Kitty',
                       traits: ['hintomint','seafoam','swampgreen','saycheese']},

  ## 2017
  ## December
  phuziqaat:    { name: 'Phu Ziqaat',    date: '2017-12-31',  limit: 1000,  desc: 'Alien Kitty',
                   traits: ['chartreux','spock','alien','pouty']},
  santaclaws:   { name: 'Santa Claws',   date: '2017-12-12',  limit: 1000, overflow: 2, desc: 'Ho Ho Ho - Santa Claus Kitty',
                    traits: ['cloudwhite','scarlet','beard','wild_d']},
  mistletoe:    { name: 'Mistletoe',     date: '2017-12-09',  limit: 2000,  desc: "XMas Kitty",
                   traits: ['odlace','crazy','gerbil']},
  dracula:      { name: 'Dracula',       date: '2017-12-01',  limit: 2000,
                   traits: ['laperm','spock','strawberry','WE01']},

  ## November
  ducat:        { name: 'Du Cat',        date: '2017-11-29',  limit: 10_000,
                    traits: ['cymric','tongue']},
  genesis:      { name: 'Genesis',       date: '2017-11-24',  limit: 1,     exclusive: true, ids: [1],  desc: '1st Kitty'},
  shipcat:      { name: 'Ship Cat',      date: '2017-11-23',  limit: 2000,
                    traits: ['sphynx','orangesoda','luckystripe','crazy']},
  bugcat:       { name: 'Bug Cat',       date: '2017-11-23',  limit: 3,     exclusive: true, ids: [101,102,103], desc: 'Bug Bounty Kitty' },
}
TRAIT_IDS_CACHE =

todo/fix:

make trait_ids_cache more (re)usable - fix global!!!!
{}
TRAITS_TIMELINE =
{
  ## 2018
  ## november
  dune:           { date: '2018-11-21' },
  secretgarden:   { date: '2018-11-21' },
  floorislava:    { date: '2018-11-21' },
  junglebook:     { date: '2018-11-21' },

  meowgarine:     { date: '2018-11-16' },
  cornflower:     { date: '2018-11-16' },
  icicle:         { date: '2018-11-16' },
  hotcocoa:       { date: '2018-11-16' },
  firstblush:     { date: '2018-11-16' },

  featherbrain:   { date: '2018-11-13' },
  foghornpawhorn: { date: '2018-11-13' },
  alicorn:        { date: '2018-11-13' },
  wyrm:           { date: '2018-11-13' },

  mittens:        { date: '2018-11-06' },
  arcreactor:     { date: '2018-11-06' },
  allyouneed:     { date: '2018-11-06' },
  gyre:           { date: '2018-11-06' },
  moonrise:       { date: '2018-11-06' },

  ## october
  metime:      { date: '2018-10-26' },
  jacked:      { date: '2018-10-26' },
  prism:       { date: '2018-10-26' },

  isotope:     { date: '2018-10-23' },
  bridesmaid:   { date: '2018-10-23' },
  downbythebay: { date: '2018-10-23' },
  gemini:       { date: '2018-10-23' },
  kaleidoscope: { date: '2018-10-23' },

  ## thatsawrap: { date: '2018-10-21' },    ## todo: move prestige to fancies!!!
  ## duckduckcat: { date: '2018-10-19' },   ## todo: move prestige to fancies!!!

  siberian: { date: '2018-10-17' },
  lynx: { date: '2018-10-17' },
  toyger:  { date: '2018-10-17' },
  burmilla:  { date: '2018-10-17' },
  liger:  { date: '2018-10-17' },

  moue: { date: '2018-10-10' },
  majestic: { date: '2018-10-10' },
  satiated: { date: '2018-10-10' },
  struck: { date: '2018-10-10' },
  delite: { date: '2018-10-10' },

  myparade: { date: '2018-10-03' },
  roadtogold: { date: '2018-10-03' },


  ## september
  dreamboat: { date: '2018-09-21' },
  fallspice: { date: '2018-09-21' },
  mallowflower: { date: '2018-09-21' },
  hanauma: { date: '2018-09-21' },
  summerbonnet: { date: '2018-09-21' },

  ## prune: { date: '2018-09-19' },     ## todo: move prestige to fancies!!!
  ## furball: { date: '2018-09-19' },   ## todo: move prestige to fancies!!!

  firedup: { date: '2018-09-06' },
  hacker: { date: '2018-09-06' },
  drama: { date: '2018-09-06' },
  candyshoppe: { date: '2018-09-06' },

  asif: { date: '2018-09-05' },

  ## august
  dragonwings: { date: '2018-08-29' },
  aflutter: { date: '2018-08-29' },
  ducky: { date: '2018-08-29' },

  chantilly: { date: '2018-08-23' },
  mekong: { date: '2018-08-23' },
  fox: { date: '2018-08-23' },
  lykoi: { date: '2018-08-23' },

  tundra: { date: '2018-08-17' },
  glacier: { date: '2018-08-17' },
  hyacinth: { date: '2018-08-17' },
  shamrock: { date: '2018-08-17' },

  inflatablepool: { date: '2018-08-08' },
  peppermint: { date: '2018-08-08' },
  ooze: { date: '2018-08-08' },
  cyborg: { date: '2018-08-08' },

  scorpius: { date: '2018-08-01' },
  splat:   { date: '2018-08-01' },
  vigilante:  { date: '2018-08-01' },
  avatar:   { date: '2018-08-01' },

  ## july
  topoftheworld: { date: '2018-07-25' },
  confuzzled:  { date: '2018-07-25' },
  samwise: { date: '2018-07-25' },
  walrus: { date: '2018-07-25' },

  olive: { date: '2018-07-20' },
  pinefresh: { date: '2018-07-20' },
  oasis: { date: '2018-07-20' },
  dioscuri: { date: '2018-07-20' },

  juju: { date: '2018-07-18' },
  frozen: { date: '2018-07-18' },

  kalahari: { date: '2018-07-13' },
  atlantis: { date: '2018-07-13' },

  fangtastic: { date: '2018-07-06' },

  ## june
  littlefoot: { date: '2018-06-29' },
  dragontail: { date: '2018-06-29' },

  padparadscha: { date: '2018-06-28' },
  rosequartz:   { date: '2018-06-28' },
  universe:     { date: '2018-06-28' },

  martian:   { date: '2018-06-22' },
  redvelvet: { date: '2018-06-22' },
  brownies:  { date: '2018-06-22' },

  wowza: { date: '2018-06-19' },
  tendertears: { date: '2018-06-19' },

  impish: { date: '2018-06-14' },

  finalfrontier:  { date: '2018-06-11' },

  cobalt:     { date: '2018-06-09' },
  cashewmilk: { date: '2018-06-09' },
  buttercup:  { date: '2018-06-09' },

  manul:  { date: '2018-06-05' },
  balinese: { date: '2018-06-05' },
  kurilian: { date: '2018-06-05' },

  ## may
  unicorn:  { date: '2018-05-31' },
  flapflap: { date: '2018-05-31' },

  dahlia:    { date: '2018-05-29' },
  palejade:  { date: '2018-05-29' },
  autumnmoon: { date: '2018-05-29' },

  razzledazzle: { date: '2018-05-24' },
  highsociety:  { date: '2018-05-24' },
  rorschach:    { date: '2018-05-24' },

  tinybox: { date: '2018-05-19' },

  butterscotch: { date: '2018-05-10' },
  garnet:  { date: '2018-05-10' },
  mertail: { date: '2018-05-10' },
  pearl:   { date: '2018-05-10' },

  highlander:  { date: '2018-05-08' },
  koladiviya:  { date: '2018-05-08' },

  swarley: { date: '2018-05-04' },
  oceanid: { date: '2018-05-04' },
  chameleon: { date: '2018-05-04' },
  bornwithit: { date: '2018-05-04' },

  ## april
  cinderella: { date: '2018-04-27' },
  lavender:   { date: '2018-04-27' },

  daemonhorns: { date: '2018-04-24' },
  salty:       { date: '2018-04-24' },

  shale: { date: '2018-04-19' },

  eclipse:  { date: '2018-04-17' },
  parakeet: { date: '2018-04-17' },

  daemonwings:   { date: '2018-04-13' },

  caffeine:      { date: '2018-04-10' },

  frosting:         { date: '2018-04-02' },
  patrickstarfish:  { date: '2018-04-02' },
  mintmacaron:      { date: '2018-04-02' },


  ## march
  doridnudibranch:  { date: '2018-03-30' },

  springcrocus:     { date: '2018-03-20' },

  thunderstruck:    { date: '2018-03-16' },
  rascal:           { date: '2018-03-16' },

  dragonfruit:  { date: '2018-03-14' },

  belch:  { date: '2018-03-09' },

  pixiebob:    { date: '2018-03-08' },
  poisonberry: { date: '2018-03-08' },
  safetyvest:  { date: '2018-03-08' },

  cyan:  { date: '2018-03-05' },


  ## february
  missmuffett: { date: '2018-02-28' },
  wiley:      { date: '2018-02-28' },

  dippedcone:   { date: '2018-02-23' },
  leopard:      { date: '2018-02-23' },

  harbourfog:   { date: '2018-02-20' },

  baddate:      { date: '2018-02-13' },

  wuvme:  { date: '2018-02-12' },
  yokel:  { date: '2018-02-12' },
  starstruck:  { date: '2018-02-12' },

  egyptiankohl: { date: '2018-02-09' },
  bobtail: { date: '2018-02-09' },

  tiger: { date: '2018-02-06' },

  birman: { date: '2018-02-02' },
  coralsunrise: { date: '2018-02-02' },

  ## january
  forgetmenot: { date: '2018-01-30' },
  savannah: { date: '2018-01-30' },
  norwegianforest: { date: '2018-01-30' },
  twilightsparkle: { date: '2018-01-30' },

  trioculus: { date: '2018-01-26' },

  morningglory: { date: '2018-01-20' },
  apricot:      { date: '2018-01-20' },
  turtleback:   { date: '2018-01-20' },
  wasntme:      { date: '2018-01-20' },
  cheeky:       { date: '2018-01-20' },

  sapphire:     { date: '2018-01-17' },

  nachocheez:  { date: '2018-01-14' },
  koala:       { date: '2018-01-14' },
  chronic:     { date: '2018-01-14' },
  onyx:        { date: '2018-01-14' },
  sass:        { date: '2018-01-14' },

  slyboots:   { date: '2018-01-13' },

  azaleablush:   { date: '2018-01-10' },
  spangled:      { date: '2018-01-10' },

  lilac:         { date: '2018-01-09' },
  bananacream:   { date: '2018-01-09' },
  verdigris:     { date: '2018-01-09' },

  neckbeard:    { date: '2018-01-06' },
  grim:         { date: '2018-01-06' },
  grimace:      { date: '2018-01-06' },
  stunned:      { date: '2018-01-06' },

  wonky:        { date: '2018-01-04' },
  babypuke:     { date: '2018-01-04' },
  pumpkin:      { date: '2018-01-04' },

  thundergrey:   { date: '2018-01-03' },


  ## 2017
  ## december
  selkirk:       { date: '2017-12-31' },
  icy:           { date: '2017-12-31' },
  flamingo:      { date: '2017-12-31' },
  seafoam:       { date: '2017-12-31' },

  elk:           { date: '2017-12-28' },

  hintomint:      { date: '2017-12-22' },

  serpent:        { date: '2017-12-20' },
  alien:          { date: '2017-12-20' },
}

Instance Method Summary collapse

Instance Method Details

#active_recordObject

3rd party gems



15
# File 'lib/copycats.rb', line 15

require 'active_record'

#connect(config = {}) ⇒ Object



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/copycats/import/setup.rb', line 4

def connect( config={} )
  if config.empty?
    puts "ENV['DATBASE_URL'] - >#{ENV['DATABASE_URL']}<"

    ### change default to ./copycats.db ?? why? why not?
    db = URI.parse( ENV['DATABASE_URL'] || 'sqlite3:///kitties.db' )

    if db.scheme == 'postgres'
        config = {
          adapter: 'postgresql',
          host: db.host,
          port: db.port,
          username: db.user,
          password: db.password,
          database: db.path[1..-1],
          encoding: 'utf8'
        }
    else # assume sqlite3
       config = {
         adapter: db.scheme, # sqlite3
         database: db.path[1..-1] # world.db (NB: cut off leading /, thus 1..-1)
       }
    end
  end


  puts "Connecting to db using settings: "
  pp config
  ActiveRecord::Base.establish_connection( config )
  ActiveRecord::Base.logger = Logger.new( STDOUT )
  ## ActiveRecord::Base.colorize_logging = false  - no longer exists - check new api/config setting?

  ## if sqlite3 add (use) some pragmas for speedups
  if config[:adapter] == 'sqlite3'
      ## check/todo: if in memory e.g. ':memory:' no pragma needed!!
      con = ActiveRecord::Base.connection
      con.execute( 'PRAGMA synchronous=OFF;' )
      con.execute( 'PRAGMA journal_mode=OFF;' )
      con.execute( 'PRAGMA temp_store=MEMORY;' )
  end
end

#enumeratorObject

needed for each_slice



9
# File 'lib/copycats.rb', line 9

require 'enumerator'

#find_datafiles(root = '.') ⇒ Object

load all *.file in data folder



6
7
8
9
10
11
12
13
# File 'lib/copycats/import/read.rb', line 6

def find_datafiles( root='.' )
  files = []
  ## todo/check: include all subfolders - why? why not?
  Dir.glob( root + '/**/*.csv' ).each do |file|
    files << file
  end
  files
end

#read_datafiles(data_dir: './data') ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/copycats/import/read.rb', line 16

def read_datafiles( data_dir: './data' )
  files = find_datafiles( data_dir )
  pp files

  ## todo: check if files found


  ## for speed - turn off logging for info/debug/etc. levels
  ActiveRecord::Base.logger.level = :warn


  ## pp TRAIT_IDS_CACHE

  ## add / read / load all datafiles
  files.each_with_index do |file,i|

    puts "== #{i+1}/#{files.size} reading datafile '#{file}'..."


    kitties_headers = CsvReader.header( file )
    pp kitties_headers

    ##  todo: fix - use field index not name!!!! - why? why not?
    ## check format
    if kitties_headers.include?( 'id' ) &&
       kitties_headers.include?( 'gen' ) &&
       kitties_headers.include?( 'matron_id' ) &&
       kitties_headers.include?( 'sire_id' ) &&
       kitties_headers.include?( 'birthdate' ) &&
       kitties_headers.include?( 'genes' ) &&
       kitties_headers.include?( 'name' )
       ## "standard" format
       ##   required headers include: id, gen, matron_id, sire_id, birthdate, genes, name

       ##  todo: fix - use field index not name!!!! - why? why not?
       headers = {
         'id'         => 'id',
         'gen'        => 'gen',
         'matron_id'  => 'matron_id',
         'sire_id'    => 'sire_id',
         'birthdate'  => 'birthdate',
         'genes'      => 'genes',
         'name'       => 'name'
       }
    elsif kitties_headers.include?( 'id' ) &&
          kitties_headers.include?( 'matron_id' ) &&
          kitties_headers.include?( 'sire_id' ) &&
          kitties_headers.include?( 'gen' ) &&
          kitties_headers.include?( 'birth_date' ) &&
          kitties_headers.include?( 'genes_kai' )
      ## "kittydex" format
      ##   see  https://cryptokittydex.com/resources
      ##    required headers include: id, matron_id, sire_id, gen, birth_date, genes_kai
       headers = {
         'id'         => 'id',
         'matron_id'  => 'matron_id',
         'sire_id'    => 'sire_id',
         'gen'        => 'gen',
         'birthdate'  => 'birth_date',
         'genes'      => 'genes_kai',
         'name'       => 'name'   ## note: will always be nil (is missing in kittydex)
       }
    else
      ## unknown format
      puts "!!! unknown datafile format; matching headers NOT found / missing"
      exit 1
    end


    ## start of kitties blockchain / genesis
    genesisdate = Date.new( 2017, 11, 23)   ## 2017-11-23

    ## note: for now use first 5 rows for testing
    ## kitties[0..4].each do |row|

    kitties = CsvHash.read( file )
    kitties.each do |row|
      ## puts row['id'] + '|' + row['gen'] + '|' + row['genes_kai']
      k = Copycats::Model::Kitty.new
      k.id        = row[headers['id']].to_i
      k.gen       = row[headers['gen']].to_i
      k.matron_id = row[headers['matron_id']].to_i   unless row[headers['matron_id']].blank? || row[headers['matron_id']] == '0'
      k.sire_id   = row[headers['sire_id']].to_i     unless row[headers['sire_id']].blank?   || row[headers['sire_id']] == '0'
      k.name      = row[headers['name']]             unless row[headers['name']].blank?

      ##  founder cats - first one hundret (1 to 100 - note: includes genesis (1))
      k.is_founder = true    if k.id >= 1 && k.id <= 100


      ## todo: pretty print (format genes !!!!)
      k.genes_kai = row[headers['genes']]   ### .gsub( ' ', '' )  ## remove all spaces - why? why not?

      ##  pp row['birthdate']
      birthdate = DateTime.strptime( row[headers['birthdate']], '%Y-%m-%d %H:%M:%S' )
      k.birthdate =  birthdate
      k.day_count = (birthdate.to_date.jd - genesisdate.jd)+1


      genome = Genome.new( k.genes_kai )
      genes =  genome.genes

      k.body_id      = TRAIT_IDS_CACHE[:body][:kai][genes[:body].d]
      k.pattern_id   = TRAIT_IDS_CACHE[:pattern][:kai][genes[:pattern].d]
      k.coloreyes_id = TRAIT_IDS_CACHE[:coloreyes][:kai][genes[:coloreyes].d]
      k.eyes_id      = TRAIT_IDS_CACHE[:eyes][:kai][genes[:eyes].d]
      k.color1_id    = TRAIT_IDS_CACHE[:color1][:kai][genes[:color1].d]
      k.color2_id    = TRAIT_IDS_CACHE[:color2][:kai][genes[:color2].d]
      k.color3_id    = TRAIT_IDS_CACHE[:color3][:kai][genes[:color3].d]
      k.wild_id      = TRAIT_IDS_CACHE[:wild][:kai][genes[:wild].d]
      k.mouth_id     = TRAIT_IDS_CACHE[:mouth][:kai][genes[:mouth].d]

      ## pp k

      ## print ids for progress report - why? why not?
      print "#{k.id}."
      k.save!

      ## add genes
      TRAITS.each_with_index do |(trait_key, trait_hash),i|
        gene    = genes[trait_key]
        next  if gene.nil?   ## skip future_1, future_2, etc. for now - add - why? why not?

        ##  puts "#{trait_hash[:name]} (Genes #{trait_hash[:genes]})\n\n"

        ## note: start counting for d.n with 1 (NOT 0)
        ##  use idx for zero-based counting - why? why not?

        d = Copycats::Model::Gene.new
        d.kitty_id = k.id
        d.n        = (i*4)     # gene number/pos  0-47  (start w/ 1 why? why not?)
        d.gene     = 'd'     # d (0), r1 (1), r2 (2), r3 (3)
        d.gene_n   = 0       # 0-3  (0=d,1=r1,2=r2,3=r3)
        d.trait_id = TRAIT_IDS_CACHE[trait_key][:kai][gene.d]
        d.save!

        r1 = Copycats::Model::Gene.new
        r1.kitty_id = k.id
        r1.n        = (i*4)+1     # gene number/pos  0-47  (start w/ 1 why? why not?)
        r1.gene     = 'r1'     # d (0), r1 (1), r2 (2), r3 (3)
        r1.gene_n   = 1       # 0-3  (0=d,1=r1,2=r2,3=r3)
        r1.trait_id = TRAIT_IDS_CACHE[trait_key][:kai][gene.r1]
        r1.save!

        r2 = Copycats::Model::Gene.new
        r2.kitty_id = k.id
        r2.n        = (i*4)+2   # gene number/pos  0-47  (start w/ 1 why? why not?)
        r2.gene     = 'r2'     # d (0), r1 (1), r2 (2), r3 (3)
        r2.gene_n   = 2       # 0-3  (0=d,1=r1,2=r2,3=r3)
        r2.trait_id = TRAIT_IDS_CACHE[trait_key][:kai][gene.r2]
        r2.save!

        r3 = Copycats::Model::Gene.new
        r3.kitty_id = k.id
        r3.n        = (i*4)+3     # gene number/pos  0-47  (start w/ 1 why? why not?)
        r3.gene     = 'r3'     # d (0), r1 (1), r2 (2), r3 (3)
        r3.gene_n   = 3       # 0-3  (0=d,1=r1,2=r2,3=r3)
        r3.trait_id = TRAIT_IDS_CACHE[trait_key][:kai][gene.r3]
        r3.save!
      end

    end
    print "\n"
  end
end

#setup_dbObject



47
48
49
50
# File 'lib/copycats/import/setup.rb', line 47

def setup_db
  ## build schema
  CreateDb.new.up
end

#setup_traitsObject



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/copycats/import/setup.rb', line 59

def setup_traits
  ## for speed - turn off logging for info/debug/etc. levels
  ActiveRecord::Base.logger.level = :warn

  ### add traits
  TRAITS.each do |trait_key, trait_hash|

    trait_t = Copycats::Model::TraitType.new
    trait_t.name = trait_hash[:name]
    trait_t.key  = trait_key.to_s
    trait_t.save!

    cache = {}

    Kai::ALPHABET.each_with_index do |kai,n|
      name = trait_hash[:kai][kai]
      name = '?'  if name.nil? || name.empty?

      tier = Gene::TIER[kai]

      puts "Kai: #{kai} (#{n}) /#{tier}, Cattribute: #{name}"
      trait  = Copycats::Model::Trait.new
      trait.name          = name
      trait.kai           = kai
      trait.n             = n
      trait.tier          = tier
      trait.trait_type_id = trait_t.id
      trait.save!

      cache[ kai ] = trait.id
    end

    TRAIT_IDS_CACHE[ trait_key ] = { id:  trait_t.id,
                                     kai: cache }
  end
end