(->> const err = -> console.error it const fetch-log = -> fetch it .then (-> console.log it it ) .catch err const $opponent-hand = document.query-selector '#opponent-hand' const $own-hand = document.query-selector '#own-hand' const $view-card = document.query-selector '#view-card' const $view-card-container = document.query-selector '#view-card-container' const $param = document.query-selector '#param' const $play = document.query-selector '#play' const $discard-pile = document.query-selector '#discard-pile' const $discard-pile-img = document.query-selector '#discard-pile-img' const $discard-pile-count = document.query-selector '#discard-pile-count' const $shadow-realm = document.query-selector '#shadow-realm' const $shadow-realm-img = document.query-selector '#shadow-realm-img' const $shadow-realm-count = document.query-selector '#shadow-realm-count' const $deck = document.query-selector '#deck' const $deck-count = document.query-selector '#deck-count' const $extra = document.query-selector '#extra' const [push-param, pop-param] = (-> param = "" clear-param-timer = 0 setInterval (-> clear-param-timer-- if clear-param-timer param := "" unless clear-param-timer $param.inner-text = param && "\xa0#param\xa0" ), 100 const push-param = -> param += it $param.inner-text = "\xa0#param\xa0" clear-param-timer := 20 const pop-full-param = -> ret = param param := "" $param.inner-text = "\xa0#param\xa0" if ret == "" 1 else +ret [push-param, pop-full-param] )! play-id-list = "" const clamp = (n, v, x) -> Math.min (Math.max v, n), x const unwrap_uuid = (.replace /^\{|\}$/g '') const get-play-size = -> $play.get-bounding-client-rect! const gen-array = -> Array.from { length: it }, (_, i) -> i const gen-array-of = (it, val) -> Array.from { length: it }, -> val const cards = await fetch-log \./cards.json .then (.json!) const $make-card = -> $img = document.create-element \img $img.src = it $img const $make-blank-card = -> $make-card \./card_back.png const gen-opponent-cards$ = -> diff = it - $opponent-hand.child-element-count switch | diff < 0 while diff++ $opponent-hand.remove-child $opponent-hand.first-child | diff > 0 $opponent-hand.append ...(gen-array diff .map $make-blank-card) | _ void const get-state = ->> player-state-json = await fetch \./get_state .then (.text!) player-state = JSON.parse player-state-json events-json = await fetch \/get_events .then (.text!) events = JSON.parse events-json play-map = new Map player-state.play.map -> [it.id, it] return { player-state-json, player-state, events-json, events, play-map } const show-card$ = (e) -> const hide-card$ = -> $view-card.style.opacity = 0 e.target.remove-event-listener \mouseleave hide-card$ $view-card.src = e.target.get-attribute \data-png $view-card.style.opacity = 1 e.target.add-event-listener \mouseleave hide-card$ state = await get-state! const apply-state$ = -> { player-state } = it gen-opponent-cards$ player-state.opponent_cards_in_hand if document.body.class-list.contains \my-turn document.body.class-list.remove \my-turn if player-state.you != player-state.turn_player else document.body.class-list.add \my-turn if player-state.you == player-state.turn_player $deck-count.inner-text = player-state.deck_size if player-state.discard_pile.length top-id = player-state.discard_pile[* - 1] $discard-pile-img.src = cards[top-id].jpg $discard-pile-img.set-attribute \data-png cards[top-id].png else $discard-pile-img.src = "" $discard-pile-count.inner-text = player-state.discard_pile.length if player-state.shadow_realm.length top-id = player-state.shadow_realm[* - 1] $shadow-realm-img.src = cards[top-id].jpg $shadow-realm-img.set-attribute \data-png cards[top-id].png else $shadow-realm-img.src = "" $shadow-realm-count.inner-text = player-state.shadow_realm.length if $extra.has-attribute \data-pile-type const list = switch $extra.get-attribute \data-pile-type | \discard => player-state.discard_pile | \shadow => player-state.shadow_realm | \deck => gen-array-of state.player-state.deck_size, null | _ => (console.log that) || [] open-list list, $extra.get-attribute \data-pile-type if player-state.hand.length != $own-hand.children.length $own-hand.innerHTML = '' player-state.hand.for-each (card-id, index) -> card-data = cards[card-id] card = $make-card card-data.jpg card ..set-attribute \data-hand-index index ..set-attribute \data-text card-data.txt ..set-attribute \data-png card-data.png ..add-event-listener \mouseenter show-card$ $own-hand.append-child card next-play-id-list = [...player-state.play.map (.play_id)].sort!join \| if play-id-list !== next-play-id-list $play.innerHTML = '' player-state.play.for-each -> card-data = cards[unwrap_uuid it.id] if it.owner == player-state.you relative-y = it.position_y else relative-y = 100 - it.position_y img = $make-card card-data.jpg img ..class-list.add \in-play-card ..style ..left = it.position_x + \% ..top = relative-y + \% ..set-attribute \data-png card-data.png ..set-attribute \data-play-id it.play_id ..set-attribute \data-play-x it.position_x ..set-attribute \data-play-y relative-y ..set-attribute \draggable \true ..set-attribute \data-owner it.owner ..set-attribute \data-owned it.owner == player-state.you ..set-attribute \data-tapped it.tapped ..add-event-listener \mouseenter show-card$ ..add-event-listener \dragstart -> it.target.set-attribute \data-start-x it.target.offset-left it.target.set-attribute \data-start-y it.target.offset-top it.target.set-attribute \data-client-x it.client-x it.target.set-attribute \data-client-y it.client-y ..add-event-listener \dragend -> const start-x = +it.target.get-attribute \data-start-x const start-y = +it.target.get-attribute \data-start-y const start-client-x = +it.target.get-attribute \data-client-x const start-client-y = +it.target.get-attribute \data-client-y const new-x = it.client-x + (start-x - start-client-x) const new-y = it.client-y + (start-y - start-client-y) const scale-x = +start-x / +(it.target.get-attribute \data-play-x) const scale-y = +start-y / +(it.target.get-attribute \data-play-y) const x = clamp 5 Math.round(new-x / scale-x), 95 const y = clamp 5 Math.round(new-y / scale-y), 95 it.target.style ..left = x + \% ..top = y + \% it.target.set-attribute \data-play-x x it.target.set-attribute \data-play-y y if state.player-state.you == it.target.get-attribute \data-owner absolute-y = y else absolute-y = 100 - y fetch-log "./move/#{it.target.get-attribute \data-play-id}/#x/#absolute-y" $play.append-child img play-id-list := next-play-id-list else player-state.play.for-each -> $element = document.query-selector "[data-play-id=\"#{it.play_id}\"]" if it.owner == player-state.you relative-y = it.position_y else relative-y = 100 - it.position_y $element.set-attribute \data-tapped it.tapped $element.style ..left = it.position_x + \% ..top = relative-y + \% $element.set-attribute \data-play-x it.position_x $element.set-attribute \data-play-y relative-y apply-state$ state const open-list = (list, list-type) --> const $card-list = list.map (card-id, index) -> if card-id ret = $make-card cards[card-id].jpg ret.set-attribute \data-png cards[card-id].png ret.set-attribute "data-index" index ret.set-attribute "data-list-type" list-type ret.add-event-listener \mouseenter show-card$ ret else $make-blank-card! $extra.innerHTML = "" $card-list.for-each -> $extra.append it $extra.set-attribute \data-pile-type list-type $extra.class-list.remove \hidden $discard-pile-img.add-event-listener \mouseenter show-card$ $shadow-realm-img.add-event-listener \mouseenter show-card$ $play.add-event-listener \dragover (.prevent-default!) $discard-pile-img.add-event-listener \click -> open-list state.player-state.discard_pile, \discard $shadow-realm-img.add-event-listener \click -> open-list state.player-state.shadow_realm, \shadow $deck.add-event-listener \click -> open-list (gen-array-of state.player-state.deck_size, null), \deck set-interval (->> const new-state = await get-state! unless new-state.player-state-json == state.player-state-json apply-state$ new-state state := new-state window.state = state ), 1000 mouse-x = mouse-y = 0 document ..add-event-listener \mousemove -> mouse-x = it.client-x mouse-y = it.client-y if mouse-x > window.inner-width * 2 / 3 $view-card-container.class-list.remove \right else if mouse-x < window.inner-width / 3 $view-card-container.class-list.add \right ..add-event-listener \keyup -> $current-mouse-node = [...document.query-selector-all \:hover][* - 1] switch it.key | \c => fetch-log "./draw/#{pop-param!}" | \e => fetch-log "./pass" | \0 \1 \2 \3 \4 \5 \6 \7 \8 \9 => push-param that | \t => if $current-mouse-node?.has-attribute \data-hand-index fetch-log "./fade/#{$current-mouse-node.get-attribute \data-hand-index}" | \y => if $current-mouse-node?.has-attribute \data-hand-index fetch-log "./fade_bottom/#{$current-mouse-node.get-attribute \data-hand-index}" | ' ' => if $current-mouse-node?.has-attribute \data-hand-index fetch-log "./play/#{$current-mouse-node.get-attribute \data-hand-index}" else if $current-mouse-node?.has-attribute \data-play-id if \true == $current-mouse-node.get-attribute \data-tapped $current-mouse-node.set-attribute \data-tapped \false else $current-mouse-node.set-attribute \data-tapped \true fetch-log "./tap/#{$current-mouse-node.get-attribute \data-play-id}" else if $current-mouse-node?.has-attribute \data-list-type switch $current-mouse-node.get-attribute \data-list-type | \discard fetch-log "./unkill/#{$current-mouse-node.get-attribute \data-index}" | \shadow fetch-log "./unbanish/#{$current-mouse-node.get-attribute \data-index}" $current-mouse-node.parent-element.remove-child $current-mouse-node if !$extra.child-element-count $extra.class-list.add \hidden $extra.remove-attribute \data-pile-type | \r => if $current-mouse-node?.has-attribute \data-play-id fetch-log "./bounce/#{$current-mouse-node.get-attribute \data-play-id}" | \d => if $current-mouse-node?.has-attribute \data-hand-index fetch-log "./discard/#{$current-mouse-node.get-attribute \data-hand-index}" else if $current-mouse-node?.has-attribute \data-play-id fetch-log "./kill/#{$current-mouse-node.get-attribute \data-play-id}" | \s => if $current-mouse-node?.has-attribute \data-hand-index fetch-log "./forget/#{$current-mouse-node.get-attribute \data-hand-index}" else if $current-mouse-node?.has-attribute \data-play-id fetch-log "./banish/#{$current-mouse-node.get-attribute \data-play-id}" | \q => $extra.class-list.add \hidden $extra.remove-attribute \data-pile-type )!