'use strict'; import { CardId, StaticData, View } from './types'; declare function action_button(action: string, text: string): void; // declare function register_action(element: HTMLElement, type: string, s: number): void; declare function send_action(action: string, text: string): boolean; declare const data: StaticData; declare const view: View; /* global view, player, send_action, action_button */ const BONUSES_COUNT = 2; // const PIECE_COUNT = 32; const CARD_COUNT = 109; const GLORY_COUNT = 9; const medallionS_COUNT = 9; const STANDEES_COUNT = 5; const TRACK_COUNT = 5; const TRACK_LENGTH = 11; const FACTIONS = ['a', 'c', 'm']; // const ROLES = ['Anarchist', 'Communist', 'Moderate']; const ui = { map: document.getElementById('map'), medallions_container: document.getElementById('medallions'), markers: document.getElementById('markers'), fronts: { a: { front: document.getElementById('aragon_front'), value: document.querySelector('#aragon_front .value'), contributions: document.querySelector('#aragon_front .contributions'), }, m: { front: document.getElementById('madrid_front'), value: document.querySelector('#madrid_front .value'), contributions: document.querySelector('#madrid_front .contributions'), }, n: { front: document.getElementById('northern_front'), value: document.querySelector('#northern_front .value'), contributions: document.querySelector('#northern_front .contributions'), }, s: { front: document.getElementById('southern_front'), value: document.querySelector('#southern_front .value'), contributions: document.querySelector('#southern_front .contributions'), }, }, glory_container: document.getElementById('glory'), hand: document.getElementById('hand'), hand_area: document.getElementById('hand_area'), current_events: document.getElementById('current_events'), roles: { a: { hero_points: document.querySelector('#role_Anarchist .role_stat'), medallions: document.querySelector('#role_Anarchist .role_medallions'), }, c: { hero_points: document.querySelector('#role_Communist .role_stat'), medallions: document.querySelector('#role_Communist .role_medallions'), }, m: { hero_points: document.querySelector('#role_Moderate .role_stat'), medallions: document.querySelector('#role_Moderate .role_medallions'), }, pool: { hero_points: document.getElementById('pool_hero_points'), }, Anarchist: document.getElementById('role_Anarchist'), Communist: document.getElementById('role_Communist'), Moderate: document.getElementById('role_Moderate'), container: document.getElementById('roles'), }, player_areas: { container: document.getElementById('player_areas'), Anarchist: document.getElementById('player_area_Anarchist'), Communist: document.getElementById('player_area_Communist'), Moderate: document.getElementById('player_area_Moderate'), }, selectable_cards: document.getElementById('selectable_cards'), tableaus: { a: document.getElementById('tableau_a'), c: document.getElementById('tableau_c'), m: document.getElementById('tableau_m'), }, tracks: document.getElementById('tracks'), hero_points: document.querySelector('#role_Anarchist .role_stat'), turn_info: document.getElementById('turn_info'), turn_info_card: document.getElementById('turn_info_card'), year: document.getElementById('year'), blank_markers: [], bonuses: [], // fronts: {}, tokens_on_front: {}, // front_values: {}, glory: [], initiative_token: undefined, medallions: [], spaces: [], standees: [], pieces: [], cards: [], }; let action_register = []; const LAYOUT_BONUSES = [ [435, 481], [493, 481], ]; const LAYOUT_CURRENT_EVENTS = [ [172, 648], [309, 648], [445, 648], [584, 648], ]; const LAYOUT_GLORY = [ [801, 647], [860, 647], [897, 647], [848, 718], [775, 771], [812, 771], [849, 771], [885, 771], [922, 771], ]; const LAYOUT_medallionS = [ [364, 556], [415, 556], [466, 556], [517, 556], [568, 556], ]; const LAYOUT_TRACKS = [ [ [581, 46], [618, 46], [655, 46], [691, 46], [728, 46], [765, 46], [801, 46], [838, 46], [874, 46], [911, 46], [948, 46], ], [ [581, 156], [618, 156], [655, 156], [691, 156], [728, 156], [765, 156], [801, 156], [838, 156], [874, 156], [911, 156], [948, 156], ], [ [581, 267], [618, 267], [655, 267], [691, 267], [728, 267], [765, 267], [801, 267], [838, 267], [874, 267], [911, 267], [948, 267], ], [ [581, 378], [618, 378], [655, 378], [691, 378], [728, 378], [765, 378], [801, 378], [838, 378], [874, 378], [911, 378], [948, 378], ], [ [581, 489], [618, 489], [655, 489], [691, 489], [728, 489], [765, 489], [801, 489], [838, 489], [874, 489], [911, 489], [948, 489], ], ]; // @ts-ignore // (function build_map() { // data.fronts.forEach((front) => { // const { id, top, left } = front; // const element = (ui.fronts[front.id] = document.createElement('div')); // element.classList.add('front'); // element.style.left = `${left}px`; // element.style.top = `${top}px`; // element.setAttribute('data-front-id', `${id}`); // ui.map.appendChild(element); // register_action(element, 'front', id); // // Contribution tokens // // Value of front // const front_value_element = (ui.front_values[front.id] = // document.createElement('span')); // front_value_element.classList.add('value'); // element.appendChild(front_value_element); // }); // })(); function register_action( e: HTMLElement & { my_action?: string; my_id?: string | number }, action: string, id: string | number ) { e.my_action = action; e.my_id = id; e.onmousedown = on_click_action; action_register.push(e); } function on_click_action(evt) { if (evt.button === 0) if (send_action(evt.target.my_action, evt.target.my_id)) evt.stopPropagation(); } function is_action(action, arg) { if (arg === undefined) return !!(view.actions && view.actions[action] === 1); return !!( view.actions && view.actions[action] && view.actions[action].includes(arg) ); } let on_init_once = false; function on_init() { if (on_init_once) return; on_init_once = true; // Reorder tableaus and roles based on player order for (const player of view.player_order) { ui.player_areas.container.insertAdjacentElement('beforeend', ui.player_areas[player]); ui.roles.container.insertAdjacentElement('beforeend', ui.roles[player]); } ui.roles.container.insertAdjacentElement('beforeend', ui.turn_info); if (view.current === 'Observer') { ui.hand_area.style.display = 'none'; } // Create blank_markers for (let t = 0; t < TRACK_COUNT; ++t) { for (let s = 0; s < TRACK_LENGTH; ++s) { const bm = t * 11 + s; let e = (ui.blank_markers[bm] = document.createElement('div')); e.className = 'blank_marker'; register_action(e, 'blank_marker', bm); } } // create bonus markers for (let b = 0; b < BONUSES_COUNT; ++b) { let e = (ui.bonuses[b] = document.createElement('div')); e.className = 'bonus'; e.setAttribute('data-bonus-id', '' + b); e.style.left = LAYOUT_BONUSES[b][0] + 'px'; e.style.top = LAYOUT_BONUSES[b][1] + 'px'; LAYOUT_BONUSES; register_action(e, 'bonus', b); ui.map.appendChild(ui.bonuses[b]); } // Create glory for (let g = 0; g < GLORY_COUNT; ++g) { let e = (ui.glory[g] = document.createElement('div')); e.className = 'faction_token'; ui.glory_container.appendChild(ui.glory[g]); e.style.left = LAYOUT_GLORY[g][0] + 'px'; e.style.top = LAYOUT_GLORY[g][1] + 'px'; } // create track medallions for (let m = 0; m < medallionS_COUNT; ++m) { let e = (ui.medallions[m] = document.createElement('div')); e.className = 'medallion'; e.setAttribute('data-medallion-id', '' + m); register_action(e, 'medallion', m); } // create track standees for (let s = 0; s < STANDEES_COUNT; ++s) { let e = (ui.standees[s] = document.createElement('div')); e.className = 'standee'; e.setAttribute('data-standee-id', '' + s); register_action(e, 'standee', s); ui.tracks.appendChild(ui.standees[s]); } // create card elements for (let c = 1; c < CARD_COUNT; ++c) { let e = (ui.cards[c] = document.createElement('div')); e.className = 'card'; e.setAttribute('data-card-id', '' + data.cards[c].id); register_action(e, 'card', c); } // create initiative marker let e = (ui.initiative_token = document.createElement('div')); e.className = 'initiative_token'; // create tokens to add to fronts data.fronts.forEach((front) => { ui.tokens_on_front[front.id] = {}; FACTIONS.forEach((faction_id) => { let e = (ui.tokens_on_front[front.id][faction_id] = document.createElement('div')); e.className = 'faction_token'; e.setAttribute('data-faction-id', faction_id); }); }); Object.keys(ui.fronts).forEach((front_id) => { register_action(ui.fronts[front_id].front, 'front', front_id); }); } function place_cards(e: HTMLElement, cards: CardId[]) { e.replaceChildren(); for (let c of cards) { ui.cards[c].classList.remove('selected'); e.appendChild(ui.cards[c]); if (view.selected_cards.includes(c)) { ui.cards[c].classList.add('selected'); } } } // @ts-ignore function on_update() { console.log('on_update', view); on_init(); for (let key of Object.keys(view.hero_points)) { ui.roles[key].hero_points.replaceChildren( `Hero Points: ${view.hero_points[key]}` ); } // for (let s = 0; s < SPACE_COUNT; ++s) ui.spaces[s].replaceChildren(); // for (let p = 0; p < PIECE_COUNT; ++p) { // let s = view.location[p]; // ui.spaces[s].appendChild(ui.pieces[p]); // } ui.current_events.replaceChildren(); for (let i = 0; i < view.current_events.length; i++) { const cardId = view.current_events[i]; ui.current_events.appendChild(ui.cards[cardId]); ui.cards[cardId].classList.add('event'); ui.cards[cardId].style.left = LAYOUT_CURRENT_EVENTS[i][0] + 'px'; ui.cards[cardId].style.top = LAYOUT_CURRENT_EVENTS[i][1] + 'px'; } ui.markers.replaceChildren(); for (let bm of view.triggered_track_effects) { const s = bm % 11; const t = Math.floor(bm / 11); ui.markers.appendChild(ui.blank_markers[bm]); ui.blank_markers[bm].style.left = LAYOUT_TRACKS[t][s][0] + 'px'; ui.blank_markers[bm].style.top = LAYOUT_TRACKS[t][s][1] + 'px'; } for (let bonus_id of Object.keys(view.bonuses)) { ui.bonuses[bonus_id].setAttribute( 'data-bonus-on', view.bonuses[bonus_id] + 0 ); } place_cards(ui.hand, view.hand); place_cards(ui.selectable_cards, view.selectable_cards); for (let faction_id of FACTIONS) { place_cards(ui.tableaus[faction_id], view.tableaus[faction_id]); } for (let i = 0; i < view.tracks.length; ++i) { // ui.tracks.appendChild(ui.standees[i]); ui.standees[i].style.left = LAYOUT_TRACKS[i][view.tracks[i]][0] + 'px'; ui.standees[i].style.top = LAYOUT_TRACKS[i][view.tracks[i]][1] + 'px'; } for (let front_id of Object.keys(view.fronts)) { const front_data = view.fronts[front_id]; // ui.fronts[front_id].value.replaceChildren(front_data.value); ui.fronts[front_id].value.replaceChildren( front_data.status !== null ? front_data.status : front_data.value ); ui.fronts[front_id].contributions.replaceChildren(); for (let faction_id of front_data.contributions) { ui.fronts[front_id].contributions.appendChild( ui.tokens_on_front[front_id][faction_id] ); } } ui.medallions_container.replaceChildren(); for (let i = 0; i < view.medallions.pool.length; ++i) { if (view.medallions.pool[i] !== null) { const id = view.medallions.pool[i]; ui.medallions[id].style.left = LAYOUT_medallionS[i][0] + 'px'; ui.medallions[id].style.top = LAYOUT_medallionS[i][1] + 'px'; ui.medallions_container.appendChild(ui.medallions[id]); } } for (let f of FACTIONS) { ui.roles[f].medallions.replaceChildren(); for (let m of view.medallions[f]) { ui.roles[f].medallions.appendChild(ui.medallions[m]); } } ui.roles[view.initiative].medallions.appendChild(ui.initiative_token); ui.initiative_token.setAttribute('data-year', view.year); if (view.played_card === null) { ui.turn_info.style.display = 'none'; } else { ui.turn_info.style.display = ''; ui.turn_info_card.setAttribute('data-card-id', view.played_card + ''); } for (let g = 0; g < view.glory.length; ++g) { ui.glory[g].setAttribute('data-faction-id', view.glory[g]); } for (let e of action_register) e.classList.toggle('action', is_action(e.my_action, e.my_id)); ui.year.replaceChildren(`Year ${view.year}`); action_button('add_to_front', '+1 to a Front'); action_button('d_liberty', 'Decrease Liberty'); action_button('soviet_support', 'Soviet Support'); action_button('collectivization', 'Collectivization'); action_button('d_collectivization', 'Decrease Collectivization'); action_button('d_foreign_aid', 'Decrease Foreign Aid'); action_button('d_government', 'Decrease Government'); action_button('d_soviet_support', 'Decrease Soviet Support'); action_button('foreign_aid', 'Foreign Aid'); action_button('government', 'Government'); action_button('liberty', 'Liberty'); action_button('government_to_center', 'Government towards center'); action_button('teamwork_on', 'Teamwork Bonus On'); action_button('Anarchist', 'Anarchist'); action_button('Communist', 'Communist'); action_button('Moderate', 'Moderate'); action_button('gain_hp', 'Gain Hero Points'); action_button('lose_hp', 'Lose Hero Points'); action_button('draw_card', 'Draw a card'); action_button('draw_cards', 'Draw cards'); // action_button('draw_card', 'Draw card'); action_button('play_for_ap', 'Play card for Action Points'); action_button('play_for_event', 'Play card for Event'); action_button('use_ap', 'Use Action Points'); action_button('use_morale_bonus', 'Use Morale Bonus'); action_button('add_glory', 'Add to Bag of Glory'); action_button('up', 'Up'); action_button('down', 'Down'); action_button('next', 'Next'); action_button('remove_blank_marker', 'Remove Blank marker'); action_button('confirm', 'Confirm'); action_button('yes', 'Yes'); action_button('no', 'No'); action_button('skip', 'Skip'); action_button('done', 'Done'); action_button('spend_hp', 'Spend Hero Points'); action_button('undo', 'Undo'); } // @ts-ignore function on_log(text) { let p = document.createElement('div'); if (text.match(/^>>/)) { text = text.substring(2); p.className = 'ii'; } if (text.match(/^>/)) { text = text.substring(1); p.className = 'i'; } text = text.replace(/&/g, '&'); text = text.replace(//g, '>'); // text = text.replace(/C(\d+)/g, sub_card_name) // text = text.replace(/S(\d+)/g, sub_space_name) // text = text.replace(/U(\d+)/g, sub_unit_name) // TODO dice icons // text = text.replace(/\bD\d\b/g, sub_icon) if (text.match(/^\.h1/)) { text = text.substring(4); p.className = 'h1'; } else if (text.match(/^\.h2\.Moderate/)) { text = text.substring(13); p.className = 'h2 moderate'; } else if (text.match(/^\.h2\.Anarchist/)) { text = text.substring(14); p.className = 'h2 anarchist'; } else if (text.match(/^\.h2\.Communist/)) { text = text.substring(14); p.className = 'h2 communist'; } else if (text.match(/^\.h2\.fascist/)) { text = text.substring(11); p.className = 'h2 fascist'; } else if (text.match(/^\.h2/)) { text = text.substring(4); p.className = 'h2'; } else if (text.match(/^\.h3/)) { text = text.substring(4); p.className = 'h3'; } p.innerHTML = text; return p; }