Skip to content

Instantly share code, notes, and snippets.

@gabrielflorit
Last active January 30, 2019 03:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gabrielflorit/7f370bc716aff805f593a3f80008711f to your computer and use it in GitHub Desktop.
Save gabrielflorit/7f370bc716aff805f593a3f80008711f to your computer and use it in GitHub Desktop.
SCRIPT-8
// title: platformer
// TODO:
// use sprites and map to draw tiles
// why am i drawing them via code?!
// clean up the gettiles / scanning code, it's atrocious
const rad2Deg = ø => ø * 180 / Math.PI
const tileTile = (a, b) => {
const r1RightEdgePastR2Left = a.x + 8 >= b.x
const r1LeftEdgePastR2Right = a.x <= b.x + 8
const r1TopEdgePastR2Bottom = a.y + 8 >= b.y
const r1BottomEdgePastR2Top = a.y <= b.y + 8
const collision =
r1RightEdgePastR2Left &&
r1LeftEdgePastR2Right &&
r1TopEdgePastR2Bottom &&
r1BottomEdgePastR2Top
// If we had a collision, try to find the side.
if (collision) {
let side
const angle = rad2Deg(Math.atan2(b.y - a.y, a.x - b.x))
if (angle > 45 && angle < 90 + 45) {
side = 'top'
} else {
side = 'other'
}
return side
} else {
return false
}
}
const getTileCoordsVertical = (d, offset) => {
const row = Math.ceil(Math.floor(d.y) / 8) + offset
const col = Math.floor(d.x / 8)
const onX = Math.floor(d.x) % 8 === 0
return onX ? [[row, col]] : [[row, col], [row, col + 1]]
}
const getTileCoordsHorizontal = (d, offset) => {
const row = Math.ceil(Math.floor(d.y) / 8)
const col = Math.floor(d.x / 8) + offset
const onX = Math.floor(d.x) % 8 === 0
const onY = Math.floor(d.y) % 8 === 0
if (onX) {
return onY ? [[row, col]] : [[row - 1, col], [row, col]]
} else {
return onY ? [[row, col + 1]] : [[row - 1, col + 1], [row, col + 1]]
}
}
const getTileCoordsUnderneath = d => getTileCoordsVertical(d, 1)
const getTileCoordsOverhead = d => getTileCoordsVertical(d, -1)
const getTileCoordsToRight = d => getTileCoordsHorizontal(d, 1)
const getTileCoordsToLeft = d => getTileCoordsHorizontal(d, -1)
const coordsToTiles = (coords, roomNumber) =>
coords.map(([row, col]) => rooms[roomNumber][row][col])
const getTilesToLeft = (d, roomNumber) =>
coordsToTiles(getTileCoordsToLeft(d), roomNumber)
const getTilesToRight = (d, roomNumber) =>
coordsToTiles(getTileCoordsToRight(d), roomNumber)
const getTilesOverhead = (d, roomNumber) =>
coordsToTiles(getTileCoordsOverhead(d), roomNumber)
const getTilesUnderneath = (d, roomNumber) =>
coordsToTiles(getTileCoordsUnderneath(d), roomNumber)
const drawRoom = state => {
rooms[state.room].forEach((cols, rowNumber) => {
cols.forEach((cell, i) => {
sprite(i * 8, rowNumber * 8, cell, cell === 32 ? -3 : -1)
})
})
}
const sprites = {
mario: {
idle: [...range(21).map(d => 0), 7],
walk: [1, 2, 3, 4, 5, 6],
prejump: [8],
jump: [9],
fall: [10],
postfall: [8],
piping: [8]
},
bowser: {
idle: [...range(10).map(d => 16), 17, ...range(10).map(d => 16)],
walk: [18, 19, 20, 19]
},
coin: {
idle: [...range(40).map(d => 48), 49, 48, 50, 48, 49, 48, 50]
}
}
const rooms = [
[
[],
[32, 35, 36, ...range(13).map(i => 32)],
[32, 51, 52, ...range(12).map(i => null), 32],
[32, ...range(14).map(i => null), 32],
[32, ...range(14).map(i => null), 32],
[32, ...range(14).map(i => null), 32],
[32, ...range(14).map(i => null), 32],
[32, ...range(14).map(i => null), 32],
[32, ...range(14).map(i => null), 32],
[32, ...range(12).map(i => null), ...range(3).map(i => 32)],
[32, ...range(14).map(i => null), 32],
[32, ...range(14).map(i => null), 32],
[...range(3).map(i => 32), ...range(12).map(i => null), 32],
[32, ...range(14).map(i => null), 32],
[32, ...range(12).map(i => null), 37, 38, 32],
[32, ...range(12).map(i => 32), 53, 54, 32]
],
[
[],
[32, 35, 36, ...range(13).map(i => 32)],
[32, 51, 52, ...range(12).map(i => null), 32],
[32, ...range(14).map(i => null), 32],
[32, ...range(14).map(i => null), 32],
[32, ...range(14).map(i => null), 32],
[32, ...range(14).map(i => null), 32],
[32, ...range(14).map(i => null), 32],
[32, ...range(14).map(i => null), 32],
[...range(3).map(i => 32), ...range(12).map(i => null), 32],
[32, ...range(14).map(i => null), 32],
[32, ...range(14).map(i => null), 32],
[32, ...range(12).map(i => null), ...range(3).map(i => 32)],
[32, ...range(14).map(i => null), 32],
[32, ...range(12).map(i => null), 37, 38, 32],
[32, ...range(12).map(i => 32), 53, 54, 32]
]
]
const fsm = new StateMachine({
init: 'idle',
transitions: [
{ name: 'leftright', from: 'idle', to: 'walk' },
{ name: 'noleftright', from: 'walk', to: 'idle' },
{ name: 'a', from: 'idle', to: 'prejump' },
{ name: 'a', from: 'walk', to: 'prejump' },
{ name: 'launch', from: 'prejump', to: 'jump' },
{ name: 'falling', from: 'jump', to: 'fall' },
{ name: 'sinkholed', from: 'idle', to: 'fall' },
{ name: 'sinkholed', from: 'walk', to: 'fall' },
{ name: 'landed', from: 'fall', to: 'postfall' },
{ name: 'bounce', from: 'fall', to: 'prejump' },
{ name: 'recovered', from: 'postfall', to: 'idle' },
{ name: 'die', from: 'idle', to: 'idle' },
{ name: 'die', from: 'walk', to: 'idle' },
{ name: 'die', from: 'prejump', to: 'idle' },
{ name: 'die', from: 'jump', to: 'idle' },
{ name: 'die', from: 'fall', to: 'idle' },
{ name: 'die', from: 'postfall', to: 'idle' },
{ name: 'pipe', from: 'idle', to: 'piping' },
{ name: 'piped', from: 'piping', to: 'idle' }
]
})
const e = {
mario: {
maxDx: 100 / 100,
maxDy: 4,
bounceBonus: 95
}
}
const defaultMario = () => ({
x: 8 + 4,
y: 8 * 2,
flip: false,
counter: 0,
dx: 0,
dy: 0,
mode: 'idle'
})
const defaultBowser = () => ({
x: 48,
y: 112,
dx: +0.5,
mode: 'walk',
flip: false,
counter: 0
})
const defaultGame = () => ({
lives: 3,
coins: 0,
counter: 0,
room: 0
})
const defaultCoin = () => ({
acquired: false,
counter: 0
})
const assignToObject = (object, properties) => {
Object.entries(properties).forEach(([key, value]) => {
object[key] = value
})
}
const resetMario = mario => {
assignToObject(mario, defaultMario())
}
const resetBowser = bowser => {
assignToObject(bowser, defaultBowser())
}
const resetCoin = coin => {
assignToObject(coin, defaultCoin())
}
const resetGame = state => {
assignToObject(state, defaultGame())
resetMario(state.actors.find(d => d.name === 'mario'))
resetBowser(state.actors.find(d => d.name === 'bowser'))
resetCoin(state.actors.find(d => d.name === 'coin'))
}
initialState = {
mode: 'intro',
...defaultGame(),
actors: [
{
name: 'mario',
...defaultMario()
},
{
name: 'bowser',
start: 48,
end: 8 * 10,
...defaultBowser()
},
{
name: 'coin',
x: 8 * 13,
y: 8 * 8,
mode: 'idle',
...defaultCoin()
}
]
}
const moveHorizontally = ({ mario, input, state }) => {
const { maxDx } = e.mario
if (input.left) {
mario.dx = clamp(mario.dx - 0.5, -maxDx, maxDx)
mario.flip = true
} else if (input.right) {
mario.dx = clamp(mario.dx + 0.5, -maxDx, maxDx)
mario.flip = false
} else {
mario.dx = Math.sign(mario.dx) * Math.max(Math.abs(mario.dx) - 0.25, 0)
}
// Prevent mario from moving into a tile.
if (Math.floor(mario.x) % 8 === 0) {
if (mario.dx < 0) {
const tiles = getTilesToLeft(mario, state.room).filter(d => d)
if (tiles.length) {
mario.dx = 0
}
}
if (mario.dx > 0) {
const tiles = getTilesToRight(mario, state.room).filter(d => d)
if (tiles.length) {
mario.dx = 0
}
}
}
mario.x += mario.dx
}
const isOnGround = ({ state, mario }) => {
// If the y-coordinate isn't at a multiple of 8,
// we're obviously not on ground.
if (Math.floor(mario.y) % 8 !== 0) {
return false
} else {
// Try to get the one or two tiles underneath:
const tiles = getTilesUnderneath(mario, state.room)
// If we're exactly on one tile,
if (tiles.length === 1) {
// only check that one.
return !!tiles[0]
} else {
// If we're in between two tiles, at least one of them needs to be there.
return !!tiles[0] || !!tiles[1]
}
}
}
const moveBowser = ({ bowser, state }) => {
let nextMode = bowser.mode
if (bowser.mode === 'idle') {
state.counter % 6 === 0 && bowser.counter++
if (bowser.counter > 20) {
nextMode = 'walk'
}
}
if (bowser.mode === 'walk') {
bowser.flip = bowser.dx < 0
bowser.x += bowser.dx
if (bowser.x > bowser.end || bowser.x <= bowser.start) {
nextMode = 'idle'
bowser.dx *= -1
}
state.counter % 6 === 0 && bowser.counter++
}
if (bowser.mode !== nextMode) {
bowser.counter = 0
}
bowser.mode = nextMode
}
const moveMario = ({ mario, input, state, bowser, coin }) => {
if (fsm.state === 'idle') {
moveHorizontally({ state, mario, input })
state.counter % 6 === 0 && mario.counter++
mario.isOnGround = isOnGround({ state, mario })
!mario.isOnGround && fsm.can('sinkholed') && fsm.sinkholed()
if (input.left || input.right) {
fsm.can('leftright') && fsm.leftright()
}
if (input.a && fsm.can('a')) {
fsm.a()
playPhrase(1)
}
// Check if we're colliding with bowser.
mario.collidedWithBowser = tileTile(mario, bowser)
// If we are, fire the die event,
if (mario.collidedWithBowser === 'other' && fsm.can('die')) {
fsm.die()
playPhrase(3)
--state.lives
// and reset mario.
resetMario(mario)
}
// Are we pressing down?
if (input.down) {
// And are we on the ground?
if (mario.isOnGround) {
// And are we above pipe tiles?
const tilesUnderneath = getTilesUnderneath(mario, state.room)
if (
tilesUnderneath.length === 2 &&
tilesUnderneath.filter(d => d === 37 || d === 38).length === 2
) {
// And can we pipe?
if (fsm.can('pipe')) {
// Then pipe!
fsm.pipe()
playPhrase(4)
}
}
}
}
}
if (fsm.state === 'piping') {
mario.dy = 0.25
mario.y += mario.dy
// If we get to the edge of the screen,
// reset the level.
if (mario.y > 112) {
fsm.can('piped') && fsm.piped()
if (state.room < rooms.length - 1) {
++state.room
resetMario(mario)
resetBowser(bowser)
resetCoin(coin)
} else {
state.mode = 'win'
}
}
}
if (fsm.state === 'walk') {
// Move horizontally.
moveHorizontally({ state, mario, input })
// Increase counter.
state.counter % 4 === 0 && mario.counter++
// Check if we're still on ground.
mario.isOnGround = isOnGround({ state, mario })
// If we're not on ground, try firing `sinkholed` event.
!mario.isOnGround && fsm.can('sinkholed') && fsm.sinkholed()
// If we aren't pressing left or right,
if (!input.left && !input.right) {
// try firing `noleftright` event.
fsm.can('noleftright') && fsm.noleftright()
}
// If we're pressing `a`, and we can fire the `a` event,
if (input.a && fsm.can('a')) {
// fire it,
fsm.a()
// and play the jump phrase.
playPhrase(1)
}
// Check if we're colliding with bowser.
mario.collidedWithBowser = tileTile(mario, bowser)
// If we are, fire the die event,
if (mario.collidedWithBowser === 'other' && fsm.can('die')) {
fsm.die()
--state.lives
playPhrase(3)
// and reset mario.
resetMario(mario)
}
}
if (fsm.state === 'prejump') {
moveHorizontally({ state, mario, input })
mario.dy =
-e.mario.maxDy -
(mario.collidedWithBowser ? e.mario.bounceBonus / 100 : 0)
mario.counter++
mario.counter === 2 && fsm.can('launch') && fsm.launch()
// Check if we're colliding with bowser.
mario.collidedWithBowser = tileTile(mario, bowser)
// If we are, fire the die event,
if (mario.collidedWithBowser === 'other' && fsm.can('die')) {
fsm.die()
--state.lives
playPhrase(3)
// and reset mario.
resetMario(mario)
}
}
if (fsm.state === 'jump') {
moveHorizontally({ state, mario, input })
const prevDy = mario.dy
// Decrease jump speed.
mario.dy = Math.min(mario.dy + 0.25, e.mario.maxDy)
// We can only move as far as the next tile.
// So, get the tiles overhead.
const tiles = getTilesOverhead(mario, state.room)
// If there are tiles, find the safe y distance to travel.
let safeDy
if (tiles.filter(d => d).length) {
safeDy = Math.max(-(mario.y % 8), mario.dy)
mario.dy = 0
} else {
safeDy = mario.dy
}
mario.y += safeDy
if (prevDy < 0 && mario.dy >= 0) {
fsm.can('falling') && fsm.falling()
}
// Check if we're colliding with bowser.
mario.collidedWithBowser = tileTile(mario, bowser)
// If we are, fire the die event,
if (mario.collidedWithBowser === 'other' && fsm.can('die')) {
fsm.die()
--state.lives
playPhrase(3)
// and reset mario.
resetMario(mario)
}
}
if (fsm.state === 'fall') {
moveHorizontally({ state, mario, input })
// Increase fall speed.
mario.dy = Math.min(mario.dy + 0.25, e.mario.maxDy)
// We can only move as far as the next tile.
// So, get the tiles underneath.
const tiles = getTilesUnderneath(mario, state.room) // e.g. [room[row][col]]
// If there are tiles, find the safe y distance to travel.
const safeDy = tiles.filter(d => d).length ? 8 - mario.y % 8 : mario.dy
mario.y += Math.min(safeDy, mario.dy)
// Check if we're colliding with bowser.
mario.collidedWithBowser = tileTile(mario, bowser)
// If we are, try firing the bounce state.
if (mario.collidedWithBowser === 'top' && fsm.can('bounce')) {
fsm.bounce()
playPhrase(2)
}
// If we are, fire the die event,
if (mario.collidedWithBowser === 'other' && fsm.can('die')) {
fsm.die()
--state.lives
playPhrase(3)
// and reset mario.
resetMario(mario)
}
// Check if we're on the ground.
mario.isOnGround = isOnGround({ state, mario })
// If we are, land.
mario.isOnGround && fsm.can('landed') && fsm.landed()
}
if (fsm.state === 'postfall') {
moveHorizontally({ state, mario, input })
mario.dy = 0
mario.counter++
mario.counter === 3 && fsm.can('recovered') && fsm.recovered()
// Check if we're colliding with bowser.
mario.collidedWithBowser = tileTile(mario, bowser)
// If we are, fire the die event,
if (mario.collidedWithBowser === 'other' && fsm.can('die')) {
fsm.die()
--state.lives
playPhrase(3)
// and reset mario.
resetMario(mario)
}
}
if (!coin.acquired && tileTile(mario, coin)) {
++state.coins
coin.acquired = true
}
// If we changed states,
if (fsm.state !== mario.mode) {
// reset counter.
mario.counter = 0
}
mario.mode = fsm.state
}
update = (state, input, elapsed) => {
if (
state.mode === 'intro' ||
state.mode === 'gameover' ||
state.mode === 'win'
) {
if (input.start) {
resetGame(state)
state.mode = 'play'
}
}
if (state.mode === 'play') {
state.counter++
const mario = state.actors.find(d => d.name === 'mario')
const bowser = state.actors.find(d => d.name === 'bowser')
const coin = state.actors.find(d => d.name === 'coin')
moveBowser({ bowser, state })
moveMario({ mario, input, state, bowser, coin })
state.counter % 5 === 0 && coin.counter++
if (state.lives < 0) {
state.mode = 'gameover'
}
}
}
const drawActor = (actor, fade) => {
if (actor.name !== 'coin' || !actor.acquired) {
const cycle = sprites[actor.name][actor.mode]
sprite(
actor.x,
actor.y,
cycle[actor.counter % cycle.length],
fade ? -3 : 0,
actor.flip
)
}
// rectStroke(actor.x, actor.y, 8, 8, fade ? 3 : 0)
if (actor.name === 'mario') {
// if (actor.collidedWithBowser) {
// print(16, 16, `state: ${actor.mode}`, 0)
// print(16, 24, `collision side: ${actor.collidedWithBowser}`, 0)
// }
// const left = getTileCoordsToLeft(actor)
// rectStroke(left[1] * 8, left[0] * 8, 8, 8, 0)
// const right = getTileCoordsToRight(actor)
// right.forEach(d => {
// rectStroke(d[1] * 8, d[0] * 8, 8, 8, 0)
// })
}
}
drawActors = (state, fade) => {
state.actors.forEach(actor => drawActor(actor, fade))
}
draw = state => {
if (state.mode === 'intro') {
rectFill(0, 0, 128, 128, 6)
print(43, 47, 'platformer', 0)
print(42, 73, 'press start', 2)
print(33, 81, 'left / right / a', 4)
}
if (state.mode === 'play') {
clear()
// Draw lives.
sprite(0, 0, 0)
print(8 + 1, 0, state.lives.toString().padStart(2, '0'), 0)
// Draw coins.
sprite(8 * 3, 0, 48)
print(8 * 4 - 1, 0, state.coins.toString().padStart(2, '0'), 0)
rectFill(0, 5, 128, 3, 7)
drawActors(state)
drawRoom(state)
}
if (state.mode === 'gameover') {
rectFill(0, 56, 128, 24, 6)
print(46, 59, 'game over', 0)
print(42, 73, 'press start', 2)
}
if (state.mode === 'win') {
rectFill(0, 56, 128, 24, 6)
print(50, 59, 'you won', 0)
print(42, 73, 'press start', 2)
}
}
{
"0": [
"0c00",
"15c00"
],
"1": [
"0d27",
"1f27",
"2a#27"
],
"2": [
"0g27",
"1b27",
"2d37"
],
"3": [
"0b27",
"1g#27",
"2f27",
"3d27",
"4b17",
"5g#17",
"6f17",
"7d17"
],
"4": [
"0b37",
"1a37",
"2g37",
"3f37",
"4d#37",
"5c#37",
"6b27",
"7a27",
"8g27",
"9f27",
"10d#27",
"11c#27",
"12b17",
"13a17",
"14g17",
"15f17"
]
}
{
"0": [
[
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
],
[
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
],
[
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
],
[
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
],
[
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
],
[
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
],
[
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
],
[
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
],
[
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
],
[
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
],
[
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
],
[
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
],
[
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
],
[
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
],
[
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
],
[
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null,
null
]
]
}
{
"0": [
" 2220 ",
" 22222",
" 20270 ",
" 200220",
" 2000 ",
" 221331 ",
"0 333351",
" 2 3 "
],
"1": [
" 2220 ",
" 22222",
" 20270 ",
" 200220",
" 2000 ",
" 22135 ",
" 20335 ",
" 223 "
],
"2": [
" 2222 ",
" 22222",
" 22027 ",
" 220022",
" 2200 ",
" 32215 ",
" 33220 ",
" 2 3 "
],
"3": [
" 2222 ",
" 22222",
" 22027 ",
" 220022",
" 2200 ",
" 322150",
" 233322 ",
" 3 "
],
"4": [
" 2220 ",
" 22222",
" 20270 ",
" 200220",
" 2000 ",
" 22135 ",
" 20335 ",
" 223 "
],
"5": [
" 2202 ",
" 22222",
" 02707 ",
" 002202",
" 0000 ",
" 221331 ",
"0 333351",
" 3 2 "
],
"6": [
" 2202 ",
" 22222",
" 02707 ",
" 002202",
" 220000 ",
"0 213310",
" 333335 ",
" 2 "
],
"7": [
" 2220 ",
" 22222",
" 20200 ",
" 200220",
" 2000 ",
" 221331 ",
"0 333351",
" 2 3 "
],
"8": [
" ",
" 2220 ",
" 22222",
" 20270 ",
" 200220",
" 222000 ",
"0 333351",
" 2 3 "
],
"9": [
" 2220 ",
" 222221",
" 2027072",
" 2002202",
" 220001 ",
"0 21335 ",
" 33353 ",
" 2 "
],
"10": [
" 20 ",
" 222221",
" 2222 2",
" 20270 2",
" 200220 ",
"0220001 ",
" 213353",
" 23335 "
],
"16": [
" 022 3 ",
" 5047000",
"05200000",
"5120022 ",
"01710001",
"52710171",
" 110021 ",
" 11 21 "
],
"17": [
" 033 3 ",
" 5022000",
"05200000",
"5120022 ",
"01710001",
"52710171",
" 110021 ",
" 11 21 "
],
"18": [
" 022 3 ",
" 5047000",
"05200000",
"5120022 ",
"0117100 ",
"552711 ",
" 110021 ",
" 11 21 "
],
"19": [
" 022 3 ",
" 5047000",
"05200000",
"5120022 ",
"0171000 ",
"5271071 ",
" 1102 ",
" 1121 "
],
"20": [
" 022 3 ",
" 5047000",
"05200000",
"5120022 ",
"17100001",
"27100171",
" 211 ",
" 211 "
],
"32": [
"00112112",
"02225223",
"12225225",
"12223225",
"13552112",
"01121223",
"12231225",
"25532555"
],
"33": [
"11111114",
"14444445",
"14445445",
"14545445",
"54555455",
"55522553",
"15231525",
"25532555"
],
"35": [
" 5400044",
" 5400044",
" 5400044",
" 5400044",
" 5400044",
" 5400044",
" 5400044",
" 5400044"
],
"36": [
"5553303 ",
"5553303 ",
"5553303 ",
"5553303 ",
"5553303 ",
"5553303 ",
"5553303 ",
"5553303 "
],
"37": [
"50000004",
"54000445",
"54000445",
"54000445",
"54000445",
"54000445",
"55555555",
" 5544455"
],
"38": [
"44440000",
"55553303",
"55553303",
"55553303",
"55553303",
"55553303",
"55555555",
"5555535 "
],
"48": [
" 000 ",
" 00100 ",
" 00100 ",
" 00100 ",
" 000 ",
" ",
" ",
" "
],
"49": [
" 110 ",
" 110 ",
" 110 ",
" 110 ",
" 110 ",
" ",
" ",
" "
],
"50": [
" 011 ",
" 011 ",
" 011 ",
" 011 ",
" 011 ",
" ",
" ",
" "
],
"51": [
" 5400044",
"40000004",
"54000445",
"54000445",
"54000445",
"54000445",
"54000445",
"55555555"
],
"52": [
"5553303 ",
"44440000",
"55553303",
"55553303",
"55553303",
"55553303",
"55553303",
"55555555"
],
"53": [
" 5400044",
" 5400044",
" 5400044",
" 5400044",
" 5400044",
" 5400044",
" 5400044",
" 5400044"
],
"54": [
"5553303 ",
"5553303 ",
"5553303 ",
"5553303 ",
"5553303 ",
"5553303 ",
"5553303 ",
"5553303 "
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment