{"version":3,"sources":["Types.ts","Conn.tsx","img/bowl0.svg","img/bowl20.svg","img/bowl40.svg","img/bowl60.svg","img/bowl80.svg","img/bowl100.svg","img/round1.svg","img/round2.svg","img/round3.svg","img/devicesetup.svg","Extras.tsx","Game.tsx","App.tsx","Instructions.tsx","index.tsx"],"names":["MessageKind","MessageStartTurn","source","seqNumber","JSON","parse","this","MessageEndTurn","COOKIE_NAME","Connection","url","onConnected","onNewState","onError","ws","id","onConnect","Cookies","console","log","uuid","expires","getID","ReconnectingWebSocket","debug","onmessage","e","onMessage","onopen","handleConnection","sendCommand","types","register","kind","data","cmd","send","stringify","evt","response","error","Modal","setAppElement","LanguageContext","React","createContext","value","Countdown","props","timerID","state","secondsLeft","deadline","dl","Math","floor","Date","now","setState","window","setInterval","tick","clearInterval","timeHM","num","seconds","seconds_padded","time_convert","className","Component","GameNav","showSettings","href","target","onClick","toggleSettings","gameName","leaveGame","GameMenu","Footer","showInstructions","show","rel","Game","showInterstitial","serverState","userGuessing","showAddTeamDialog","round","myUserID","adminUser","prevProps","setTimeout","ss","isAdmin","canStartGame","words","length","teams","newRoundText","name","src","devicesetup","round1","alt","round2","round3","bowl0","isOpen","onRequestClose","addTeam","team","disabled","startGame","addWord","style","textAlign","iAmClueing","startClueing","startGuessing","submitGuess","c","guess","endTurn","remainingWords","hide","resetGame","WordList","inputRef","createRef","wordsAdded","preventDefault","node","current","v","trim","res","commentary","onSubmit","type","autoComplete","ref","maxLength","TeamForm","teamNameRef","autoCorrect","spellCheck","autoCapitalize","aria-hidden","TeamList","currentTeam","showScore","active","timeRemaining","undefined","map","index","Team","t","score","Bowl","bowl","bowlLabel","bowlFill","bowl100","bowl80","bowl60","bowl40","bowl20","Guess","len","wordIdx","random","lastRollLen","correct","numWords","word","newIdx","cw","WordLog","useState","prevRW","setPrevRW","wordLog","setWordLog","useEffect","underscore","removed","concat","App","conn","passwordInputRef","wordQueue","process","s","msg","connected","userID","uid","message","alert","st","gameState","nwq","found","push","w","localeCompare","ignorePunctuation","sensitivity","createGame","joinGame","startTurn","htmlFor","form","withAlert","Instructions","setLanguage","l","context","Provider","contextType","ReactDOM","render","StrictMode","path","template","AlertTemplate","document","getElementById"],"mappings":"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","file":"static/js/main.53f468c0.chunk.js","sourcesContent":["/* Do not change, this code is generated from Golang structs */\n\n\nexport enum MessageKind {\n gameState = \"gameState\",\n register = \"register\",\n joinGame = \"joinGame\",\n addTeam = \"addTeam\",\n addWord = \"addWord\",\n createGame = \"createGame\",\n error = \"error\",\n leaveGame = \"leaveGame\",\n startTurn = \"startTurn\",\n endTurn = \"endTurn\",\n guess = \"guess\",\n startGame = \"startGame\",\n resetGame = \"resetGame\",\n}\nexport class Message {\n kind: MessageKind;\n data: string;\n\n static createFrom(source: any = {}) {\n return new Message(source);\n }\n\n constructor(source: any = {}) {\n if ('string' === typeof source) source = JSON.parse(source);\n this.kind = source[\"kind\"];\n this.data = source[\"data\"];\n }\n}\nexport class Team {\n name: string;\n score: number;\n\n static createFrom(source: any = {}) {\n return new Team(source);\n }\n\n constructor(source: any = {}) {\n if ('string' === typeof source) source = JSON.parse(source);\n this.name = source[\"name\"];\n this.score = source[\"score\"];\n }\n}\nexport class MessageGameState {\n name: string;\n ID: string;\n seqNumber: number;\n adminUser: string;\n round: number;\n teams: Team[];\n currentTeam: number;\n words: string[];\n remainingWords: string[];\n userGuessing?: string;\n deadline?: number;\n timeRemaining?: number;\n\n static createFrom(source: any = {}) {\n return new MessageGameState(source);\n }\n\n constructor(source: any = {}) {\n if ('string' === typeof source) source = JSON.parse(source);\n this.name = source[\"name\"];\n this.ID = source[\"ID\"];\n this.seqNumber = source[\"seqNumber\"];\n this.adminUser = source[\"adminUser\"];\n this.round = source[\"round\"];\n this.teams = this.convertValues(source[\"teams\"], Team);\n this.currentTeam = source[\"currentTeam\"];\n this.words = source[\"words\"];\n this.remainingWords = source[\"remainingWords\"];\n this.userGuessing = source[\"userGuessing\"];\n this.deadline = source[\"deadline\"];\n this.timeRemaining = source[\"timeRemaining\"];\n }\n\n\tconvertValues(a: any, classs: any, asMap: boolean = false): any {\n\t if (!a) {\n\t return a;\n\t }\n\t if (a.slice) {\n\t return (a as any[]).map(elem => this.convertValues(elem, classs));\n\t } else if (\"object\" === typeof a) {\n\t if (asMap) {\n\t for (const key of Object.keys(a)) {\n\t a[key] = new classs(a[key]);\n\t }\n\t return a;\n\t }\n\t return new classs(a);\n\t }\n\t return a;\n\t}\n}\nexport class MessageRegister {\n id: string;\n\n static createFrom(source: any = {}) {\n return new MessageRegister(source);\n }\n\n constructor(source: any = {}) {\n if ('string' === typeof source) source = JSON.parse(source);\n this.id = source[\"id\"];\n }\n}\nexport class MessageJoinGame {\n gameName: string;\n\n static createFrom(source: any = {}) {\n return new MessageJoinGame(source);\n }\n\n constructor(source: any = {}) {\n if ('string' === typeof source) source = JSON.parse(source);\n this.gameName = source[\"gameName\"];\n }\n}\nexport class MessageAddTeam {\n name: string;\n\n static createFrom(source: any = {}) {\n return new MessageAddTeam(source);\n }\n\n constructor(source: any = {}) {\n if ('string' === typeof source) source = JSON.parse(source);\n this.name = source[\"name\"];\n }\n}\nexport class MessageAddWord {\n word: string;\n\n static createFrom(source: any = {}) {\n return new MessageAddWord(source);\n }\n\n constructor(source: any = {}) {\n if ('string' === typeof source) source = JSON.parse(source);\n this.word = source[\"word\"];\n }\n}\nexport class MessageCreateGame {\n gameName?: string;\n\n static createFrom(source: any = {}) {\n return new MessageCreateGame(source);\n }\n\n constructor(source: any = {}) {\n if ('string' === typeof source) source = JSON.parse(source);\n this.gameName = source[\"gameName\"];\n }\n}\nexport class MessageError {\n error: string;\n\n static createFrom(source: any = {}) {\n return new MessageError(source);\n }\n\n constructor(source: any = {}) {\n if ('string' === typeof source) source = JSON.parse(source);\n this.error = source[\"error\"];\n }\n}\nexport class MessageStartTurn {\n seqNumber: number;\n\n static createFrom(source: any = {}) {\n return new MessageStartTurn(source);\n }\n\n constructor(source: any = {}) {\n if ('string' === typeof source) source = JSON.parse(source);\n this.seqNumber = source[\"seqNumber\"];\n }\n}\nexport class MessageEndTurn {\n seqNumber: number;\n\n static createFrom(source: any = {}) {\n return new MessageEndTurn(source);\n }\n\n constructor(source: any = {}) {\n if ('string' === typeof source) source = JSON.parse(source);\n this.seqNumber = source[\"seqNumber\"];\n }\n}\nexport class MessageGuess {\n seqNumber: number;\n word?: string;\n words?: string[];\n\n static createFrom(source: any = {}) {\n return new MessageGuess(source);\n }\n\n constructor(source: any = {}) {\n if ('string' === typeof source) source = JSON.parse(source);\n this.seqNumber = source[\"seqNumber\"];\n this.word = source[\"word\"];\n this.words = source[\"words\"];\n }\n}","import * as Cookies from 'js-cookie';\nimport uuid from 'uuid-random';\nimport ReconnectingWebSocket from 'reconnecting-websocket';\n\nimport * as types from \"./Types\";\n\n\nconst COOKIE_NAME = \"ID\";\n\ntype NewStateFunc = (state: any) => void;\n\nexport class Connection {\n ws: ReconnectingWebSocket;\n id: string;\n onNewState: NewStateFunc;\n onConnect: () => void;\n onError: (msg: string) => void;\n\n constructor(url: string, onConnected: () => void, onNewState: NewStateFunc, onError: (msg: string) => void ) {\n this.id = getID();\n this.onNewState = onNewState;\n this.ws = new ReconnectingWebSocket(url, [], { debug: true });\n this.ws.onmessage = (e) => this.onMessage(e);\n this.ws.onopen = (e) => this.handleConnection();\n this.onConnect = onConnected;\n this.onError = onError;\n }\n\n handleConnection() {\n this.sendCommand(types.MessageKind.register, { id: this.id });\n if (!!this.onConnect) {\n this.onConnect();\n }\n }\n\n public uid(): string {\n return this.id;\n }\n\n public sendCommand(kind: types.MessageKind, data: any) {\n const cmd = {\n kind: kind,\n data: data,\n };\n console.log(\"sending command\", cmd);\n this.ws.send(JSON.stringify(cmd));\n }\n\n onMessage(evt: MessageEvent) {\n console.log(\"got message\", evt.data);\n const response = JSON.parse(evt.data);\n if (!response.kind || !response.data) {\n console.log(\"invalid message\");\n }\n\n if (response.kind === \"gameState\") {\n this.onNewState(response.data);\n }\n\n if (response.kind === types.MessageKind.error) {\n this.onError(response.data.error);\n } \n\n if (response.kind === \"leaveGame\") {\n this.onNewState(null);\n }\n }\n}\n\nfunction getID(): string {\n var id = Cookies.get(COOKIE_NAME);\n if (!id) {\n id = uuid();\n console.log(\"generated id\", id);\n Cookies.set(COOKIE_NAME, id, { expires: 7 });\n } else {\n console.log(\"using existing id\", id);\n }\n\n return id;\n};","export default __webpack_public_path__ + \"static/media/bowl0.9f97189b.svg\";","export default __webpack_public_path__ + \"static/media/bowl20.a406bb69.svg\";","export default __webpack_public_path__ + \"static/media/bowl40.9938951e.svg\";","export default __webpack_public_path__ + \"static/media/bowl60.4bb5903a.svg\";","export default __webpack_public_path__ + \"static/media/bowl80.835a6185.svg\";","export default __webpack_public_path__ + \"static/media/bowl100.a80d632e.svg\";","export default __webpack_public_path__ + \"static/media/round1.b3f6835e.svg\";","export default __webpack_public_path__ + \"static/media/round2.210e1128.svg\";","export default __webpack_public_path__ + \"static/media/round3.53fd00f2.svg\";","export default __webpack_public_path__ + \"static/media/devicesetup.a3a89020.svg\";","//import * as types from \"./Types\";\nimport React from \"react\";\nimport Modal from 'react-modal';\n\nModal.setAppElement(\"#root\");\n\nexport const LanguageContext = React.createContext({value: \"EN\"});\n\n\ntype CountdownProps = { deadline: number };\ntype CountdownState = { secondsLeft: number };\nexport class Countdown extends React.Component {\n timerID: number | undefined;\n\n constructor(props: CountdownProps) {\n super(props);\n\n this.state = { secondsLeft: this.secondsLeft(props.deadline) };\n }\n\n secondsLeft(deadline: number): number {\n const dl = Math.floor(deadline - Date.now() / 1000);\n if (dl < 0) {\n return 0;\n }\n return dl;\n }\n\n tick() {\n this.setState((state, props) => ({\n secondsLeft: this.secondsLeft(props.deadline),\n }));\n }\n\n componentDidMount() {\n this.timerID = window.setInterval(() => this.tick(), 1000);\n }\n\n componentWillUnmount() {\n window.clearInterval(this.timerID);\n }\n\n render() {\n function time_convert(num: number) {\n const minutes = Math.floor(num / 60);\n const seconds = num % 60;\n var seconds_padded = \"\" + seconds;\n if (seconds < 10) {\n seconds_padded = \"0\" + seconds_padded;\n }\n\n return minutes + \":\" + seconds_padded;\n }\n var timeHM = time_convert(this.state.secondsLeft);\n\n return
{timeHM}
;\n }\n}\n\nexport class GameNav extends React.Component<\n { gameName: string, leaveGame: () => void },\n { showSettings: boolean }\n > {\n constructor(props: { gameName: string, leaveGame: () => void }) {\n super(props);\n this.state = { showSettings: false };\n }\n\n toggleSettings() {\n this.setState({ showSettings: !this.state.showSettings });\n }\n\n render() {\n return (\n
\n

B.F.O.N.

\n
this.toggleSettings()}>{this.props.gameName}\n \n \n \n {this.state.showSettings && this.props.leaveGame()} />}\n
\n\n
\n );\n }\n}\n\nclass GameMenu extends React.Component<{ leaveGame: () => void }> {\n render() {\n return (\n
\n \n
\n );\n }\n}\n\nexport class Footer extends React.Component<{}, {\n showInstructions: boolean;\n}> {\n constructor(props: {}) {\n super(props);\n this.state = { showInstructions: false };\n }\n\n setShowInstructions(show: boolean): boolean {\n this.setState({\n showInstructions: show,\n });\n return false;\n }\n\n render() {\n return (\n
\n

\n How to Play\n

\n

\n By Molly and{\" \"}\n Casey, Christmas 2020. Source.\n

\n
\n );\n }\n}","import \"./styles/Game.scss\";\nimport bowl0 from \"./img/bowl0.svg\";\nimport bowl20 from \"./img/bowl20.svg\";\nimport bowl40 from \"./img/bowl40.svg\";\nimport bowl60 from \"./img/bowl60.svg\";\nimport bowl80 from \"./img/bowl80.svg\";\nimport bowl100 from \"./img/bowl100.svg\";\nimport round1 from \"./img/round1.svg\";\nimport round2 from \"./img/round2.svg\";\nimport round3 from \"./img/round3.svg\";\nimport devicesetup from \"./img/devicesetup.svg\";\n\n\nimport React from \"react\";\nimport ScaleText from \"react-scale-text\";\nimport Modal from 'react-modal';\nimport * as underscore from \"underscore\";\n\nimport * as types from \"./Types\";\nimport * as extras from \"./Extras\";\n\nModal.setAppElement(\"#root\");\n\ntype GameProps = {\n serverState: types.MessageGameState;\n addWord: (word: string) => boolean;\n addTeam: (name: string) => void;\n guess: (word: string) => void;\n startGame: () => void;\n startGuessing: () => void;\n endTurn: () => void;\n leaveGame: () => void;\n resetGame: () => void;\n myUserID: string;\n};\n\ntype GameState = {\n showInterstitial: boolean;\n showAddTeamDialog: boolean;\n};\n\nclass Game extends React.Component {\n constructor(props: GameProps) {\n super(props);\n this.state = {\n showInterstitial: !this.props.serverState.userGuessing,\n showAddTeamDialog: (props.serverState.round === 0 && props.myUserID === props.serverState.adminUser)\n };\n }\n\n componentDidUpdate(prevProps: GameProps) {\n const round = this.props.serverState.round;\n\n if (!!this.props.serverState.userGuessing && this.state.showInterstitial) {\n this.setState({ showInterstitial: false });\n return;\n }\n\n if (round !== prevProps.serverState.round) {\n // game was reset\n if (round === 0 && !this.state.showAddTeamDialog) {\n this.setState({ showAddTeamDialog: true });\n }\n\n if (round === 0 || round === 1 || round === 4 || prevProps.serverState.userGuessing === this.props.myUserID) {\n this.setState({ showInterstitial: true });\n } else {\n window.setTimeout(() => {\n this.setState((state, props) => ({\n showInterstitial: !props.serverState.userGuessing,\n }));\n }, 5 * 1000);\n }\n }\n }\n\n render() {\n const ss = this.props.serverState;\n const isAdmin = ss.adminUser === this.props.myUserID;\n const canStartGame = (ss.words.length >= 15 && ss.teams.length >= 2);\n\n var newRoundText = (
);\n\n if (ss.round === 0) {\n if (isAdmin) {\n newRoundText = (
\n

Hey there, game host!

\n

\n Tell everyone else to go to bfon.club on their phones and enter the password:

\n
{ss.name}
\n

(Spaces and capitalization don't matter)

\n

Everyone else can start adding words to the bowl.

\n

Meanwhile, you set up the teams.

\n\n
);\n } else {\n newRoundText = (
\n
Welcome to Bowl Full of Nouns!
\n

This is a word guessing game. Open this website on a device (like a phone) that you are NOT using for video calling.

\n \n

If you haven't played before and you like reading instructions, check out the instructions. Otherwise you can just jump in and learn as you go.

\n

Your first step is to add the words to the bowl that you will be guessing throughout the game.

\n\n
);\n }\n } else if (ss.round === 1) {\n\n newRoundText = (
\n
Round 1
\n \"\"\n

The cluemeister can say almost anything to help their teammates\n guess – except the word itself, or parts of the word. No fair spelling or rhyming the word, either.\n

\n

For example:

\n
\n

Meatballs

\n

\"This is a food that you eat at IKEA.\"

\n

(Not allowed: \"These are balls made out of meat.\")

\n
\n
\n
    \n
  • Pay attention, even when it isn't your turn! You will have to guess these words in a later round.
  • \n
\n
\n\n\n
);\n } else if (ss.round === 2) {\n\n newRoundText = (\n
\n
Round 2
\n \"\"\n

The cluemeister can only say ONE (1) word and can't make extra\n noises or motions.

\n

For example:

\n
\n

Meatballs

\n

\"IKEA.\"

\n
\n\n
\n );\n } else if (ss.round === 3) {\n\n newRoundText = (\n
\n
Round 3
\n \"\"\n

No words allowed! The cluemeister must act the word out.

\n

For example:

\n
\n

Meatballs

\n

[act out eating food, then act out assembling a chair]

\n
\n
\n );\n } else if (ss.round === 4) {\n\n newRoundText = (\n
\n
The bowl is empty!
\n \"\"\n

Time to check out the final scores.

\n
\n );\n }\n\n return (\n
\n this.props.leaveGame()}\n />\n\n\n this.setState({ showInterstitial: false })} >\n
\n {newRoundText}\n

\n {(ss.round < 4) &&\n\n \n }\n {ss.round === 4 &&\n\n \n }\n

\n
\n
\n\n {this.state.showAddTeamDialog && (\n
\n this.props.addTeam(team)}\n />\n
\n\n\n\n {/* {ss.teams.length < 2 &&
\n You need to create some teams before you can start the game.\n
} */}\n\n\n\n
\n {ss.teams.length >= 2 &&\n \n }\n
\n\n
\n
\n )}\n\n {(ss.round === 0 && !this.state.showAddTeamDialog) && (\n
\n {isAdmin &&\n
\n
\n

The bowl contains {ss.words.length} words.

\n
    \n
  • Only the host (that's you!) can start the game.
  • \n
  • Start the game when there are approximately 5 words per player.
  • \n
  • Once you start the game, there's no going back!
  • \n
\n
\n {ss.words.length < 15 &&
\n There need to be at least 15 words to start. Right now the\n bowl only has {ss.words.length} words in it.\n
}\n

\n \n

\n

\n \n

\n
\n
\n }\n \n {!isAdmin &&\n
Once everyone's ready, the host will start the game.
\n }\n\n
\n )}\n {ss.round > 0 && ss.round <= 3 && (\n
\n this.props.startGuessing()}\n />\n\n {this.props.myUserID === ss.userGuessing &&\n this.props.guess(c)}\n endTurn={() => this.props.endTurn()}\n />}\n\n \n\n
\n {ss.round === 1 && (\n
\n\n \"\"\n\n
Avoid this word
\n
\n )}\n {ss.round === 2 && (\n
\n\n \"\"\n\n
Say ONE word
\n
\n )}\n {ss.round === 3 && (\n
\n\n \"\"\n\n
Actions only, no talking
\n
\n )}\n \n
\n
\n\n )}\n {ss.round >= 4 && (\n
\n {/* Game is over! */}\n {\n return;\n }}\n />\n
\n
Good game!
\n\n

Spread the #bfon love  Tell your family, friends, and coworkers!

BFON is free, forever. If you liked it, consider donating to Sea Watch.

\n\n {isAdmin &&\n
\n
\n
    \n
  • \n Want to play again? The host (that's you!) can click the shortcut below. People won't have to enter the game password again.\n
  • \n
\n
\n

\n
\n }\n {!isAdmin &&\n
\n
\n
    \n
  • \n Want to play again? Ask the host to start the game over.\n
  • \n
\n
\n
\n }\n
\n
\n )}\n
\n );\n }\n}\n\nexport default Game;\n\ntype WordListProps = {\n words: string[];\n\n addWord: (word: string) => boolean;\n};\n\nclass WordList extends React.Component {\n inputRef = React.createRef();\n\n constructor(props: WordListProps) {\n super(props);\n this.state = { wordsAdded: 0 };\n }\n\n addWord(evt: React.FormEvent) {\n evt.preventDefault();\n const node = this.inputRef.current;\n\n\n if (node) {\n const v = node.value.trim();\n if (v === \"\") {\n // alert(\"no word, ya bozo\");\n } else {\n const res = this.props.addWord(v);\n node.value = \"\";\n if (res) {\n this.setState({ wordsAdded: this.state.wordsAdded + 1 });\n }\n }\n }\n }\n\n render() {\n var commentary = (
You can add 5 more words.
);\n if (this.state.wordsAdded < 4 && this.state.wordsAdded > 0) {\n commentary = (
You can add {5 - this.state.wordsAdded} more words.
);\n } else if (this.state.wordsAdded === 4) {\n commentary =
Just 1 more word.
;\n } else if (this.state.wordsAdded >= 5) {\n commentary = (

You're done.

(Psst! If you thought of one more perfect word, you can still sneak it in.)

);\n }\n\n\n return (\n
\n\n
Fill the bowl with words.
\n\n
\n
    \n
  • \n Proper nouns\n  (Billie Eilish, Nigeria)\n
  • \n
  • \n Noun phrases\n \n  (cabernet sauvignon, bus driver)\n \n
  • \n
\n
\n
\n
    \n
  • \n Boring words\n  (chair, tv, phone)\n
  • \n
  • \n Being super specific and tricky\n  (bouquet of fragrant purple roses)\n
  • \n
\n
\n\n
this.addWord(e)}>\n
\n \n

{commentary}

\n \n
\n
\n
\n );\n }\n}\n\nclass TeamForm extends React.Component<{\n serverState: types.MessageGameState;\n addTeam: (teamName: string) => void;\n}> {\n teamNameRef = React.createRef();\n\n addTeam() {\n const node = this.teamNameRef.current;\n if (node) {\n this.props.addTeam(node.value);\n node.value = \"\";\n }\n }\n\n render() {\n return (\n
\n
Add teams
\n

Type names for 2 or more teams.

\n
\n
    \n
  • \n Fewer, larger teams mean people have more chances to guess. But if teams are too big, some people might not get a turn to be the cluemeister. Aim for maximum 4-5 people per team.\n
  • \n
  • \n We recommend naming the team after the people\n on each team, so people remember what team they are on. (For example: \"Mom Eric Grandpa\")\n
  • \n
\n\n\n {\n return;\n }}\n\n />\n\n
\n \n
\n\n
\n );\n }\n}\n\nclass TeamList extends React.Component<{\n serverState: types.MessageGameState;\n iAmClueing: boolean;\n startClueing: () => void;\n}> {\n render() {\n const ss = this.props.serverState;\n\n if (this.props.iAmClueing) {\n const team = ss.teams[ss.currentTeam];\n return (\n this.props.startClueing()}\n key={team.name}\n timeRemaining={undefined}\n />\n );\n }\n\n const teams = ss.teams.map((team, index) => (\n 0}\n active={ss.round > 0 && ss.round <= 3 && index === ss.currentTeam}\n deadline={ss.deadline}\n startClueing={() => this.props.startClueing()}\n key={team.name}\n timeRemaining={(index === ss.currentTeam && ss.timeRemaining) ? ss.timeRemaining : undefined}\n />\n ));\n return
{teams}
;\n }\n}\n\ntype TeamProps = {\n team: types.Team;\n active: boolean;\n deadline: number | undefined;\n showScore: boolean;\n timeRemaining: number | undefined;\n startClueing: () => void;\n};\n\nclass Team extends React.Component {\n render() {\n\n const t = this.props.team;\n if (this.props.active) {\n return (\n
\n
\n

{t.name}

\n\n {!!this.props.deadline && (\n
\n \n
\n )}\n {!this.props.deadline && (\n

\n \n

\n )}\n {!!this.props.timeRemaining && (\n

Still your turn! {this.props.timeRemaining} seconds remain.

\n )}\n\n
\n
\n\n

{t.score}

\n
\n
\n );\n } else\n return (\n
\n
\n\n

{t.name}

\n
\n {this.props.showScore &&\n
\n\n

{t.score}

\n\n
\n }\n
\n );\n }\n}\n// BOWL\nclass Bowl extends React.Component<{ words: number; remainingWords: number }> {\n render() {\n let bowl = bowl0;\n let bowlLabel = \"bowlImage bowl0\";\n let bowlFill = this.props.remainingWords / this.props.words;\n if (bowlFill > 0.8) {\n bowl = bowl100;\n bowlLabel = \"bowlImage bowl100\";\n } else if (bowlFill > 0.6) {\n bowl = bowl80;\n bowlLabel = \"bowlImage bowl80\";\n } else if (bowlFill > 0.4) {\n bowl = bowl60;\n bowlLabel = \"bowlImage bowl60\";\n } else if (bowlFill > 0.2) {\n bowl = bowl40;\n bowlLabel = \"bowlImage bowl40\";\n } else if (bowlFill > 0) {\n bowl = bowl20;\n bowlLabel = \"bowlImage bowl20\";\n } else {\n bowl = bowl0;\n bowlLabel = \"bowlImage bowl0\";\n }\n\n return (\n
\n {/* \n \n {this.props.remainingWords}\n \n \n {this.props.remainingWords}\n \n */}\n\n {/*

{this.props.remainingWords}

*/}\n
\n \"\"\n
\n
{this.props.remainingWords} words left
\n
\n );\n }\n}\n\ntype GuessProps = {\n serverState: types.MessageGameState;\n myUserID: string;\n submitGuess: (word: string) => void;\n endTurn: () => void;\n};\n\ntype GuessState = {\n wordIdx: number; // index into array\n lastRollLen: number;\n};\n// CLUEING WIDGET\nclass Guess extends React.Component {\n constructor(props: GuessProps) {\n super(props);\n\n const len = props.serverState.remainingWords.length\n this.state = {\n wordIdx: Math.floor(\n Math.random() * len\n ),\n lastRollLen: len,\n };\n }\n\n static getDerivedStateFromProps(props: GuessProps, state: GuessState) {\n const len = props.serverState.remainingWords.length\n if (state && len === state.lastRollLen) {\n return null;\n }\n\n return {\n wordIdx: Math.floor(\n Math.random() * len\n ),\n lastRollLen: len,\n };\n }\n\n guess(correct: boolean) {\n const numWords = this.props.serverState.remainingWords.length;\n if (!correct) {\n // reshuffle word\n if (numWords <= 1) {\n return;\n }\n\n let newIdx = Math.floor(Math.random() * numWords);\n while (newIdx === this.state.wordIdx) {\n newIdx = Math.floor(Math.random() * numWords);\n }\n\n this.setState({\n wordIdx: newIdx,\n });\n return;\n }\n\n const word = this.props.serverState.remainingWords[this.state.wordIdx];\n this.props.submitGuess(word);\n }\n\n render() {\n const ss = this.props.serverState;\n if (!ss.userGuessing || !ss.deadline) {\n return
{/* nothing */}
;\n }\n\n var cw = ss.remainingWords[this.state.wordIdx];\n if (ss.userGuessing === this.props.myUserID && !!ss.deadline) {\n return (\n
\n

\n {cw}\n

\n\n
\n\n

\n \n

\n
\n

\n \n

\n

\n \n

\n
\n\n
\n
\n );\n }\n return null;\n }\n}\n\nconst WordLog: React.FunctionComponent<{ remainingWords: string[], hide: boolean }> = (props) => {\n const [prevRW, setPrevRW] = React.useState([]);\n const [wordLog, setWordLog] = React.useState([]);\n\n React.useEffect(() => {\n // arrays unchanged? continue\n if (prevRW.length === props.remainingWords.length && underscore.difference(props.remainingWords, prevRW).length === 0) {\n return;\n }\n\n var removed: string[];\n\n // we've rolled over turns\n if (props.remainingWords.length > prevRW.length) {\n removed = prevRW;\n setPrevRW(props.remainingWords);\n } else {\n removed = underscore.difference(prevRW, props.remainingWords);\n }\n setPrevRW(props.remainingWords);\n\n for (const word of removed) {\n setWordLog(wordLog.concat(word));\n window.setTimeout(() => {\n setWordLog(wordLog => underscore.without(wordLog, word));\n }, 5 * 1000);\n }\n\n return undefined;\n }, [prevRW, props.remainingWords, wordLog]);\n\n if (props.hide || wordLog.length === 0) {\n return
;\n }\n const words = wordLog.map((word) =>

{word}

);\n return (\n
\n

Just guessed:

\n {words}\n
\n );\n};","import React from \"react\";\nimport { withAlert, AlertManager } from 'react-alert'\nimport Modal from 'react-modal';\n\nimport \"./styles/App.scss\";\n\nimport * as types from \"./Types\";\nimport { Connection } from \"./Conn\";\nimport Game from \"./Game\";\nimport * as extras from \"./Extras\";\n\nModal.setAppElement(\"#root\");\n\ntype AppState = {\n connected: boolean;\n gameState: types.MessageGameState | undefined;\n userID: string | undefined;\n};\n\ntype AppProps = { alert: AlertManager }\n\nconst LOCAL_MODE = !process.env.REACT_APP_SERVER_URL;\n\nclass App extends React.Component {\n conn: Connection | undefined;\n passwordInputRef = React.createRef();\n wordQueue: string[] = [];\n\n componentDidMount() {\n if (LOCAL_MODE) {\n this.setState({\n connected: true,\n userID: \"1111-2222\",\n //To set the \"beginning of game\" state, comment out from here...\n gameState: new types.MessageGameState({\n name: \"Crazy Llama\",\n ID: \"crazyllama\",\n //adminUser: \"1111-2222\",\n\n round: 1,\n\n teams: [\n {\n name: \"Kelsey Ame Ngoc\",\n score: 5,\n },\n {\n name: \"Sergio Casey Molly\",\n score: 2,\n }\n\n ],\n\n // set to 0 - 1 to make a certain team active\n currentTeam: 1,\n // say \"nobody is guessing\" by commenting the next two lines out\n // userGuessing: \"1111-2222\",\n // deadline: 1483150000,\n\n words: [\"astrolabe\", \"grunge rock\", \"Boutros Boutros-Ghali\", \"Babe Ruth\", \"chicken à la king\", \"greengrocer\", \"Philip Roth\", \"IHOP\", \"Laika the space dog\", \"sackbut\", \"Australian shepherd\", \"Hunchback of Notre Dame\", \"Buzz Lightyear\", \"Tesla Model X\", \"Der Spiegel\"],\n remainingWords: [\"astrolabe\", \"grunge rock\", \"Boutros Boutros-Ghali\", \"Babe Ruth\", \"chicken à la king\", \"greengrocer\", \"Philip Roth\", \"IHOP\", \"Laika the space dog\", \"sackbut\", \"Australian shepherd\", \"Hunchback of Notre Dame\", \"Buzz Lightyear\", \"Tesla Model X\", \"Der Spiegel\"],\n }),\n //... to here\n });\n return;\n }\n\n var url = \"ws://127.0.0.1:8080/ws\";\n if (!!process.env.REACT_APP_SERVER_URL) {\n url = process.env.REACT_APP_SERVER_URL;\n }\n\n this.conn = new Connection(\n url,\n () => this.onConnect(),\n (s) => this.onNewState(s),\n (msg) => this.onError(msg),\n );\n }\n\n onConnect() {\n this.setState({\n connected: true,\n userID: this.conn?.uid(),\n });\n }\n\n onError(message: string) {\n this.props.alert.show(message, {\n type: 'error',\n });\n }\n\n onNewState(st: any) {\n console.log(\"got new server state\", st);\n if (!st) {\n this.setState({\n gameState: undefined,\n });\n } else {\n this.setState({\n gameState: st,\n });\n\n // Deal with the word queue\n if (this.conn && this.wordQueue.length > 0 ){\n if (!st.userGuessing) {\n this.wordQueue = [];\n } else {\n // remove any missing words from the queue\n var nwq: string[] = [];\n for (const word of this.wordQueue) {\n var found = false;\n for (const rw of st.remainingWords) {\n if (word === rw) {\n found = true;\n break;\n }\n }\n\n // word was somehow not transmitted\n if (found) {\n console.log(\"Word \" + word + \" was not transmitted - resubmitting!\");\n nwq.push(word)\n }\n }\n\n this.wordQueue = nwq;\n if (this.wordQueue.length > 0) {\n const msg: types.MessageGuess = { seqNumber: st.seqNumber, words: this.wordQueue };\n this.conn.sendCommand(types.MessageKind.guess, msg);\n }\n }\n }\n }\n }\n\n addWord(word: string): boolean {\n word = word.trim();\n\n if (!this.state.gameState) {\n return false; //unreachable\n }\n\n for (const w of this.state.gameState.words) {\n if (word.localeCompare(w, undefined, {\n ignorePunctuation: true,\n sensitivity: \"base\",\n }) === 0) {\n this.onError(\"Hmm, that word is already in the bowl!\");\n return false;\n }\n }\n\n if (LOCAL_MODE) {\n let st = {\n gameState: this.state.gameState,\n };\n if (st.gameState) {\n st.gameState.words.push(word);\n st.gameState.remainingWords.push(word);\n }\n this.setState(st);\n return true;\n }\n\n if (!this.conn) {\n console.log(\"not connected\");\n return false;\n }\n\n const msg: types.MessageAddWord = {\n word: word,\n }\n this.conn.sendCommand(types.MessageKind.addWord, msg);\n return true;\n }\n\n createGame() {\n if (LOCAL_MODE) {\n this.setState({\n gameState: new types.MessageGameState({\n name: \"Funky Chicken\",\n ID: \"funkychicken\",\n seqNumber: 0,\n round: 0,\n teams: [],\n currentTeam: 0,\n words: [],\n remainingWords: [],\n }),\n userID: this.state.userID,\n connected: this.state.connected,\n });\n return;\n }\n\n this.setState({\n gameState: undefined,\n });\n if (!this.conn) {\n console.log(\"not connected\");\n return;\n }\n\n const msg: types.MessageCreateGame = {};\n this.conn.sendCommand(types.MessageKind.createGame, msg);\n }\n\n resetGame() {\n if (LOCAL_MODE) {\n //TODO\n return;\n }\n\n this.conn?.sendCommand(types.MessageKind.resetGame, {});\n }\n\n joinGame() {\n if (LOCAL_MODE) {\n console.log(\"BUG: cannot join game in local mode\");\n return\n }\n const node = this.passwordInputRef.current;\n if (!node) {\n console.log(\"BUG: missing node\");\n return;\n }\n const name = node.value;\n if (name === \"\") {\n this.onError(\"Please enter a password.\");\n return;\n }\n\n this.setState({\n gameState: undefined,\n });\n if (!this.conn) {\n console.log(\"not connected\");\n return;\n }\n\n const msg: types.MessageJoinGame = { gameName: name };\n this.conn.sendCommand(types.MessageKind.joinGame, msg);\n }\n\n leaveGame() {\n this.conn?.sendCommand(types.MessageKind.leaveGame, {});\n }\n\n guess(word: string) {\n if (LOCAL_MODE) {\n let st = {\n gameState: this.state.gameState,\n };\n if (!st.gameState) {\n return;\n }\n let w = st.gameState.remainingWords.filter(w => w !== word);\n st.gameState.remainingWords = w;\n st.gameState.teams[st.gameState.currentTeam].score++\n this.setState(st);\n\n return\n }\n\n if (!this.state.gameState || !this.conn) {\n return; // unreachable\n }\n \n this.wordQueue.push(word)\n\n const msg: types.MessageGuess = { seqNumber: this.state.gameState.seqNumber, words: this.wordQueue };\n this.conn.sendCommand(types.MessageKind.guess, msg);\n }\n\n addTeam(name: string) {\n name = name.trim();\n if (!name) {\n return;\n }\n if (!this.state || !this.state.gameState) {\n return; //unreachable\n }\n for (const team of this.state.gameState.teams) {\n if (team.name === name) {\n this.onError(\"That team name already exists.\");\n return;\n }\n }\n\n if (LOCAL_MODE) {\n let st = {\n gameState: this.state.gameState,\n };\n\n st.gameState.teams = st.gameState.teams.concat([{ name: name, score: 0 }]);\n\n this.setState(st);\n\n return\n }\n\n if (!this.conn) {\n return; // unreachable\n }\n\n const msg: types.MessageAddTeam = { name: name };\n this.conn.sendCommand(types.MessageKind.addTeam, msg);\n }\n\n startGame() {\n if (!this.state.gameState) { return; }\n\n if (this.state.gameState.round !== 0) { return; }\n\n if (LOCAL_MODE) {\n let st = {\n gameState: this.state.gameState,\n };\n st.gameState.remainingWords = st.gameState.words;\n st.gameState.round = 1;\n this.setState(st);\n return\n }\n\n if (!this.conn) { return; }\n\n this.conn.sendCommand(types.MessageKind.startGame, {});\n }\n\n startGuessing() {\n if (!this.state.gameState) { return; }\n\n if (this.state.gameState.round < 1 || this.state.gameState.round > 3) { return; }\n\n if (LOCAL_MODE) {\n let st = {\n gameState: this.state.gameState,\n };\n st.gameState.userGuessing = this.state.userID;\n st.gameState.deadline = Math.floor((Date.now() / 1000) + 30)\n this.setState(st);\n return\n }\n\n const msg = new types.MessageStartTurn({\n seqNumber: this.state.gameState.seqNumber,\n });\n this.conn?.sendCommand(types.MessageKind.startTurn, msg);\n }\n\n endTurn() {\n if (!this.state.gameState) { return; }\n\n if (this.state.gameState.round < 1 || this.state.gameState.round > 3) { return; }\n\n if (LOCAL_MODE) {\n let st = {\n gameState: this.state.gameState,\n };\n st.gameState.userGuessing = undefined;\n st.gameState.deadline = undefined;\n this.setState(st);\n return\n }\n\n const msg = new types.MessageEndTurn({\n seqNumber: this.state.gameState.seqNumber,\n });\n this.conn?.sendCommand(types.MessageKind.endTurn, msg);\n }\n\n render() {\n if (!this.state || !this.state.gameState || !this.state.userID) {\n return (\n
\n
\n

Bowl Full of Nouns

\n

A remote party game for 4+ people

\n
\n { (this.state && this.state.connected && this.state.userID) &&\n
\n
\n
{ e.preventDefault(); this.joinGame() }}>\n

\n \n
\n \n
\n

\n OR\n

\n
\n \n
\n
\n }\n {!(this.state && this.state.connected && this.state.userID) &&\n
\n Connecting you to BFON central. Please hold...\n
\n }\n \n
\n );\n }\n\n return (\n
\n this.addWord(word)}\n addTeam={(name: string) => this.addTeam(name)}\n guess={(word: string) => this.guess(word)}\n startGuessing={() => this.startGuessing()}\n endTurn={() => this.endTurn()}\n startGame={() => this.startGame()}\n leaveGame={() => this.leaveGame()}\n resetGame={() => this.resetGame()}\n />\n
\n );\n }\n}\n\nexport default withAlert()(App);","import React from \"react\";\nimport { validateLocaleAndSetLanguage } from \"typescript\";\n\nimport round1 from \"./img/round1.svg\";\nimport round2 from \"./img/round2.svg\";\nimport round3 from \"./img/round3.svg\";\nimport devicesetup from \"./img/devicesetup.svg\";\n\n\nimport {LanguageContext} from \"./Extras\";\n\n\n\n\nclass Instructions extends React.Component {\n\n \n\n setLanguage = (l:string)=> {\n this.context.value = l;\n \n }\n\n \n render() {\n\n\n return (\n \n \n
\n
\n \n \n {/* */}\n
\n {this.context.value === \"EN\" && \n
\n

Hi there! Welcome to BFON.

\n \n

Bowl Full of Nouns (or, as we like to call it, BFON) is an online, remote-friendly, all-ages party game for 4+ people. It is basically a souped-up version of Charades.

\n\n

You'll need to set up a video call on your favorite platform (Google Meet, Zoom, Jitsi, etc.)

In addition,\n everybody needs a phone or other device that isn't being used for the video call.

\n \n

\n

    \n
  • Use the bigger screen for the video call and the smaller screen for BFON, not the other way around. You will want a bigger view of people's faces and bodies during round 3.
  • \n
\n

\n\n \n \n

Create the game

\n

One person clicks \"Create New Game\" to start a game. This person is the \"host\" of the game.

\n

Create teams

\n

The host enters names for two or more teams.

\n

\n

    \n
  • We recommend typing the names of the people\n on each team as the team name, so people remember what team they are on. For example, \"Mom Eric Grandpa.\"
  • \n
\n

\n

Get everyone to join

\n

A game name will appear (like \"Pink Whale\").

All players should go to http://bfon.club on their phones and enter this\n name as the password.

Capitalization and spaces don't matter.

\n

Fill the bowl

\n\n

\n Each player puts 5 nouns in the bowl.

\n
\n
    \n
  • \n Proper nouns\n  (Billie Eilish, Nigeria)\n
  • \n
  • \n Noun phrases\n  (cabernet sauvignon, bus driver)\n\n
  • \n
\n
\n
\n
    \n
  • \n Boring words\n  (chair, tv, phone)\n\n
  • \n
  • \n Being complicated just to be tricky\n  (antique vase of pink tulips)\n\n
  • \n
\n
\n\n

Guess the words

\n\n\n

\n The game consists of 3 rounds. In each round, teams take turns\n trying to guess as many words as possible, earning 1 point for each word correctly guessed.

\n

One team will turn pink – that means it's their turn to guess. One person in the team decides to be the \"cluemeister\" for this turn. The cluemeister clicks the button that says

\n\n

\n \n

\n\n

The cluemeister will see words from the bowl in random order. She needs to help the rest of her team to guess as many\n words as possible in 90 seconds.

There's a catch: she needs to follow different rules for each round.\n

\n
    \n
  • \n

    Round 1

    \n \n

    The cluemeister can say anything they want to help their teammates\n guess the clue. They can't spell the word or rhyme it.\n

    \n

    \n

    Meatballs

    \n

    \"This is a food that you can eat at IKEA.\"

    \n

    (Not allowed: \"These are balls made out of meat.\")

    \n

    \n
  • \n
  • \n

    Round 2

    \n \n

    The cluemeister can only say ONE (1) word and can't make extra\n noises or motions.

    \n

    \n

    Meatballs

    \n

    \"IKEA.\"

    \n

    \n
  • \n
  • \n

    Round 3

    \n \n

    The cluemeister can't say anything, but can make motions.

    \n

    \n

    Meatballs

    \n

    [act out eating food, then act out assembling a chair]

    \n

    \n
  • \n\n
\n\n

Accidental cheating

\n

\n Mistakes happen. If the cluemeister accidentally breaks the rules, she can click \"Oops, I cheated\" and she will get a new word.\n

\n\n

Giving up

\n

\n You can't put words back. If the cluemeister's team doesn't get the word, too bad.

The cluemeister can\n end her turn at any time by clicking \"I give up\", but the rest of the time on the clock is forfeited.\n

\n

Should we choose a different cluemeister for each turn?

\n

We think so. It's the most fun when everyone gets a turn to be the cluemeister.

\n \n

End of round

\n

Each round is over when there are no more words in the bowl.

\n

Leftover time

\n

\n If the round ends with time remaining on the clock, the team that was guessing\n can start the new round using the time left.\n

\n

Scoring

\n

\n Each correctly guessed noun is worth 1 point.\n

\n
\n

Credits

\n

Written by Casey and Molly in December 2020. BFON is our way of helping everyone get through what we hope is the last gasp of the coronavirus pandemic.

\n

Thanks to playtesters Ame, Sergio, Ngọc, Kelsey, Fran, Chris, and Jennifer.

\n

Special thanks to Liz Weinbloom, who taught us this game, and WOFIGO, who made it an institution.

\n

BFON is free and will stay free. If you like it, please consider donating to Sea Watch.

\n
\n } \n {this.context.value === \"DE\" && \n
\n \n

Bowl Full of Nouns (wir nennen es BFON) ist ein Online-Gesellschafts-Spiel für mindestens 4 Spieler.

\n\n

Du brauchst ein Videoanruf einzustellen (durch z.B. Zoom, Jitsi, Google Meet), darüber hinaus braucht jeder Spieler ein Gerät, meistens ein Handy, das nicht für den Videoanruf verwendet wird.

\n\n
\n \n

Spielregeln

\n

Neues Spiel erstellen

\n

Click auf \"Create New Game,\" um ein neues Spiel aufzustellen.

\n

Teams zusammenstellen

\n

The person who created the game enters names for two teams.

Hint: we recommend typing the names of the people\non each team as the team name, so people remember what team they are on. For example, \"Mom Dave Grandpa.\"

\n

Get everyone to join

\n

A game name will appear (like \"Pink Whale\").

All players should go to http://bfon.club and enter this\nname as the password.

Capitalization and spaces don't matter.

\n

Fill the bowl

\n\n

\n Each player puts 5 nouns in the bowl.

\n
\n
    \n
  • \n Proper nouns\n  (Billie Eilish, Nigeria)\n
  • \n
  • \n Noun phrases\n  (cabernet sauvignon, bus driver)\n\n
  • \n
\n
\n
\n
    \n
  • \n Boring words\n  (chair, tv, phone)\n\n
  • \n
  • \n Being complicated just to be tricky\n  (antique vase of pink tulips)\n\n
  • \n
\n
\n\n

Guess the words

\n\n\n

\n The game consists of 3 rounds. In each round, teams take turns\ntrying to guess as many words as possible, earning 1 point for each word correctly guessed.

\n

One team will turn pink – that means it's their turn to guess. One person in the team decides to be the \"cluemeister\" for this turn. The cluemeister clicks the button that says

\n\n

\n \n

\n\n

The cluemeister will see words from the bowl in random order. She needs to help the rest of her team to guess as many\n words as possible in 90 seconds.

There's a catch: she needs to follow different rules for each round.\n

\n
    \n
  • \n

    Round 1

    \n \n

    The cluemeister can say anything they want to help their teammates\n guess the clue. They can't spell the word or rhyme it.\n

    \n

    \n

    Meatballs

    \n

    \"This is a food that you can eat at IKEA.\"

    \n

    \n
  • \n
  • \n

    Round 2

    \n \n

    The cluemeister can only say ONE (1) word and can't make extra\n noises or motions.

    \n

    \n

    Meatballs

    \n

    \"IKEA.\"

    \n

    \n
  • \n
  • \n

    Round 3

    \n \n

    The cluemeister can't say anything, but can make motions.

    \n

    \n

    Meatballs

    \n

    [act out eating food, then act out assembling a chair]

    \n

    \n
  • \n\n
\n\n

Accidental cheating

\n

\n Mistakes happen. If the cluemeister accidentally breaks the rules, she can click \"Oops, I cheated\" and she will get a new word.\n

\n\n

Giving up

\n

\n You can't put words back. If the cluemeister's team doesn't get the word, too bad.

The cluemeister can\n end her turn at any time by clicking \"I give up\", but the rest of the time on the clock is forfeited.\n

\n

Should we choose a different cluemeister for each turn?

\n

We think so. It's the most fun when everyone gets a turn to be the cluemeister.

\n

Words that don't make sense

\n

\n There is no way to throw out words. Maybe we'll make that in a future version. For now, you have to work with what you got.\n

\n

End of round

\n

Each round is over when there are no more words in the bowl.

\n

Leftover time

\n

\n If the round ends with time remaining on the clock, the team that was guessing\n can start the new round using the time left.\n

\n

Scoring

\n

\n Each correctly guessed noun is worth 1 point. The game corrects for\n any unfairness in case one team got more play time than other teams.\n

\n
\n

Credits

\n

Written by Casey and Molly in December 2020. BFON is our way of helping everyone get through (what we hope is) the last gasp of the coronavirus pandemic.

\n

Thanks to playtesters Ame, Sergio, Ngọc, and Kelsey.

\n

Special thanks to Liz Weinbloom, who taught us this game, and WOFIGO, who made it an institution.

\n

BFON is free, forever. If you liked it, consider donating to Sea Watch.

\n
\n }\n
\n\n\n\n\n\n
\n )\n \n }\n \n}\n\nInstructions.contextType = LanguageContext;\n\nexport default Instructions;","import React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport \"./index.css\";\nimport App from \"./App\";\n\nimport {\n BrowserRouter as Router,\n Switch,\n Route} from \"react-router-dom\";\n\nimport Instructions from \"./Instructions\";\n\nimport { Provider as AlertProvider } from 'react-alert'\nimport AlertTemplate from 'react-alert-template-mui'\n//import reportWebVitals from \"./reportWebVitals\";\n\nReactDOM.render(\n \n \n \n \n \n \n \n \n \n \n \n \n \n ,\n document.getElementById(\"root\")\n);\n\n// If you want to start measuring performance in your app, pass a function\n// to log results (for example: reportWebVitals(console.log))\n// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals\n//reportWebVitals(console.log);\n"],"sourceRoot":""}