@@ -3,7 +3,7 @@ import { Command, DB } from '../imports/types'
33import { getInsult } from '../imports/tools'
44import fs from 'fs'
55
6- async function parseTriviaList ( fileName : string ) {
6+ async function parseTriviaList ( fileName : string ) : Promise < Map < string , string [ ] > > {
77 const data = await fs . promises . readFile ( `./triviaLists/${ fileName } .txt` , 'utf8' )
88 const triviaList = new Map < string , string [ ] > ( )
99 data . split ( '\n' ) . forEach ( el => {
@@ -22,7 +22,7 @@ export class TriviaSession {
2222 questionList : Map < string , string [ ] >
2323 scores : { [ id : string ] : number } = { }
2424 stopped = false
25- timer : number = null
25+ timer : number | null = null
2626 timeout = Date . now ( )
2727 count = 0
2828 tempDB : DB
@@ -38,25 +38,29 @@ export class TriviaSession {
3838 this . client = client
3939 }
4040
41- getScores ( addMedals = false ) {
41+ getScores ( addMedals = false ) : { embed : EmbedOptions } {
4242 const currentScores = Object . entries ( this . scores ) . sort ( ( [ , a ] , [ , b ] ) => b - a )
4343 const medals : { [ id : string ] : string } = { }
4444 if ( addMedals ) {
45- const maxReduce = ( a : number , b : number ) => Math . max ( a || 0 , b || 0 )
45+ const maxReduce = ( a : number , b : number ) : number => Math . max ( a || 0 , b || 0 )
4646 const values = Object . values ( this . scores )
4747 const first = values . reduce ( maxReduce )
4848 const second = values . filter ( num => num !== first ) . reduce ( maxReduce , 0 )
4949 const third = values . filter ( num => num !== first && num !== second ) . reduce ( maxReduce , 0 )
5050 currentScores . forEach ( ( [ id , b ] ) => {
51- medals [ id ] = first && b === first ? '🥇 '
52- : second && b === second ? '🥈 '
51+ medals [ id ] = first && b === first
52+ ? '🥇 '
53+ : second && b === second
54+ ? '🥈 '
5355 : third && b === third ? '🥉 ' : ''
5456 } )
5557 }
5658 const member = this . message . member . guild . members . get ( this . client . user . id )
57- const color = member ? ( member . roles . map ( i => member . guild . roles . get ( i ) ) . sort (
58- ( a , b ) => a . position > b . position ? - 1 : 1
59- ) . find ( i => i . color !== 0 ) || { color : 0 } ) . color : 0
59+ const color = member
60+ ? ( member . roles . map ( i => member . guild . roles . get ( i ) ) . sort (
61+ ( a , b ) => a . position > b . position ? - 1 : 1
62+ ) . find ( i => i . color !== 0 ) || { color : 0 } ) . color
63+ : 0
6064 const embed : EmbedOptions = {
6165 title : 'Scores' ,
6266 color,
@@ -70,14 +74,14 @@ export class TriviaSession {
7074 return { embed }
7175 }
7276
73- async endGame ( ) {
77+ async endGame ( ) : Promise < void > {
7478 this . stopped = true
7579 delete this . tempDB . trivia [ this . channel . id ]
7680 if ( Object . keys ( this . scores ) . length > 0 ) await this . channel . createMessage ( this . getScores ( true ) )
7781 }
7882
79- async newQuestion ( ) {
80- for ( let i of Object . values ( this . scores ) ) {
83+ async newQuestion ( ) : Promise < boolean > {
84+ for ( const i of Object . values ( this . scores ) ) {
8185 if ( i === this . settings . maxScore ) {
8286 await this . endGame ( )
8387 return true
@@ -107,7 +111,7 @@ export class TriviaSession {
107111
108112 if ( this . currentQuestion === null ) {
109113 await new Promise ( resolve => setTimeout ( resolve , 1000 ) )
110- if ( this . stopped === false ) await this . newQuestion ( )
114+ if ( ! this . stopped ) await this . newQuestion ( )
111115 } else if ( this . stopped ) {
112116 return true
113117 } else {
@@ -129,11 +133,11 @@ export class TriviaSession {
129133 await this . channel . createMessage ( message )
130134 await this . channel . sendTyping ( )
131135 await new Promise ( resolve => setTimeout ( resolve , 1000 ) )
132- if ( this . stopped === false ) await this . newQuestion ( )
136+ if ( ! this . stopped ) await this . newQuestion ( )
133137 }
134138 }
135139
136- async checkAnswer ( message : Message ) {
140+ async checkAnswer ( message : Message ) : Promise < boolean > {
137141 if ( message . author . bot || this . currentQuestion === null ) {
138142 return false
139143 }
@@ -142,8 +146,8 @@ export class TriviaSession {
142146
143147 // TODO: fuse.js for better pattern matching.
144148 for ( let i = 0 ; i < this . currentQuestion [ 1 ] . length ; i ++ ) {
145- let answer = this . currentQuestion [ 1 ] [ i ] . toLowerCase ( )
146- let guess = message . content . toLowerCase ( )
149+ const answer = this . currentQuestion [ 1 ] [ i ] . toLowerCase ( )
150+ const guess = message . content . toLowerCase ( )
147151 if ( ! answer . includes ( ' ' ) ) { // Strict answer checking for one word answers
148152 const guessWords = guess . split ( ' ' )
149153 for ( let j = 0 ; j < guessWords . length ; j ++ ) {
@@ -173,49 +177,47 @@ export const handleTrivia: Command = {
173177 opts : {
174178 description : 'Start a trivia game on a topic of your choice.' ,
175179 fullDescription : `Start a trivia game on a topic of your choice.
176- **Default settings:** IveBot gains points : no, seconds to answer: 15, points needed to win: 30, reveal answer on timeout : yes` ,
177- usage : `/trivia <topic> (--bot-plays=true|false ) (--time-limit=<time longer than 4s >) (--max-score=<points greater than 0>) (--reveal-answer=true|false )
178- **During a trivia game:** /trivia (scoreboard/score/scores/stop)
180+ **Default settings:** IveBot plays : no, seconds to answer: 15, points to win: 30, reveal answer: yes` ,
181+ usage : `/trivia <topic> (botplays ) (revealanswer) (timelimit=<5 seconds or more >) (pointstowin=<1 point or more> )
182+ **During a trivia game:** /trivia (scoreboard/score/scores/stop/end )
179183**To view available topics:** /trivia list` ,
180- example : '/trivia greekmyth --bot-plays=true ' ,
184+ example : '/trivia greekmyth botplays ' ,
181185 guildOnly : true ,
182186 argsRequired : true
183187 } ,
184- generator : async ( message : Message , args : string [ ] , { tempDB, client } ) => {
188+ generator : async ( message , args , { tempDB, client } ) => {
185189 let botPlays = false
186190 let timeLimit = 15000
187191 let maxScore = 30
188192 let revealAnswer = true
189193
190- // TODO: Flag soup can be handled better.
191- if ( args . find ( element => element . includes ( '--bot-plays=' ) ) ) {
192- if ( args . find ( element => element . includes ( '--bot-plays=' ) ) . split ( '=' ) [ 1 ] === 'true' ) {
194+ const botPlaysFlag = args . find ( element => element . startsWith ( 'botplays=' ) || element === 'botplays' )
195+ if ( botPlaysFlag ) {
196+ if ( botPlaysFlag . split ( '=' ) [ 1 ] === 'true' || botPlaysFlag === 'botplays ') {
193197 botPlays = true
194- } else if ( args . find ( element => element === '--bot-plays=' ) . split ( '=' ) [ 1 ] !== 'false' ) {
195- return 'Invalid usage. It must be either true or false.'
198+ } else if ( botPlaysFlag . split ( '=' ) [ 1 ] !== 'false' ) {
199+ return 'Invalid usage. `botplays` must be either true or false.'
196200 }
197201 }
198- if ( args . find ( element => element . includes ( '--time-limit=' ) ) ) {
199- if ( + args . find ( element => element . includes ( '--time-limit=' ) ) . split ( '=' ) [ 1 ] > 4 ) {
200- timeLimit = + args . find ( element => element . includes ( '--time-limit=' ) ) . split ( '=' ) [ 1 ] * 1000
201- } else {
202- return 'Invalid usage. It must be a number greater than 4.'
203- }
202+ const timeLimitFlag = args . find ( element => element . startsWith ( 'timelimit=' ) ) ?. split ( '=' )
203+ if ( timeLimitFlag ) {
204+ if ( ! isNaN ( + timeLimitFlag [ 1 ] ) && + timeLimitFlag [ 1 ] > 4 ) timeLimit = + timeLimitFlag [ 1 ] * 1000
205+ else return 'Invalid usage. `timelimit` must be a number greater than 4.'
204206 }
205- if ( args . find ( element => element . includes ( '--max-score=' ) ) ) {
206- if ( + args . find ( element => element . includes ( '--max-score=' ) ) . split ( '=' ) [ 1 ] > 0 ) {
207- maxScore = + args . find ( element => element . includes ( '--max-score' ) ) . split ( '=' ) [ 1 ]
208- } else {
209- return 'Invalid usage. It must be a number greater than 0.'
210- }
207+ const maxScoreFlag = args . find ( element => element . startsWith ( 'pointstowin=' ) ) ?. split ( '=' )
208+ if ( maxScoreFlag ) {
209+ if ( + maxScoreFlag [ 1 ] > 0 ) maxScore = + maxScoreFlag [ 1 ]
210+ else return 'Invalid usage. `pointstowin` must be a number greater than 0.'
211211 }
212- if ( args . find ( element => element . includes ( '--reveal-answer=' ) ) ) {
213- if ( args . find ( element => element . includes ( '--reveal-answer=' ) ) . split ( '=' ) [ 1 ] === 'false' ) {
212+ const revealAnswerFlag = args . find ( element => element . startsWith ( 'revealanswer=' ) || element === 'revealanswer' )
213+ if ( revealAnswerFlag ) {
214+ if ( revealAnswerFlag . split ( '=' ) [ 1 ] === 'false' ) {
214215 revealAnswer = false
215- } else if ( args . find ( element => element === '--reveal-answer =') . split ( '=' ) [ 1 ] !== 'true' ) {
216- return 'Invalid usage. It must be either true or false.'
216+ } else if ( revealAnswerFlag . includes ( ' =') && revealAnswerFlag . split ( '=' ) [ 1 ] !== 'true' ) {
217+ return 'Invalid usage. `revealanswer` must be either true or false.'
217218 }
218219 }
220+
219221 if ( args . length === 1 && [ 'scores' , 'score' , 'leaderboard' ] . includes ( args [ 0 ] ) ) {
220222 const session = tempDB . trivia [ message . channel . id ]
221223 if ( session ) {
@@ -226,16 +228,16 @@ export const handleTrivia: Command = {
226228 } else if ( args . length === 1 && args [ 0 ] === 'list' ) {
227229 const lists = await fs . promises . readdir ( './triviaLists/' )
228230 const member = message . member . guild . members . get ( client . user . id )
229- const color = member ? ( member . roles . map ( i => member . guild . roles . get ( i ) ) . sort (
230- ( a , b ) => a . position > b . position ? - 1 : 1
231- ) . find ( i => i . color !== 0 ) || { color : 0 } ) . color : 0
232- const embed : EmbedOptions = {
233- title : 'Available trivia lists' ,
234- color,
235- fields : lists . map ( name => ( { name : name . replace ( '.txt' , '' ) , value : '_ _' , inline : true } ) )
231+ const color = member
232+ ? ( member . roles . map ( i => member . guild . roles . get ( i ) ) . sort (
233+ ( a , b ) => a . position > b . position ? - 1 : 1
234+ ) . find ( i => i . color !== 0 ) || { color : 0 } ) . color
235+ : 0
236+ return {
237+ content : '❔ **Available trivia topics:**' ,
238+ embed : { color, description : lists . map ( name => `**${ name . replace ( '.txt' , '' ) } **` ) . join ( ', ' ) }
236239 }
237- return { embed }
238- } else if ( args . length === 1 && args [ 0 ] === 'stop' ) {
240+ } else if ( args . length === 1 && ( args [ 0 ] === 'stop' || args [ 0 ] === 'end' ) ) {
239241 const session = tempDB . trivia [ message . channel . id ]
240242 const channel = message . channel as GuildTextableChannel
241243 if ( session ) {
0 commit comments