グカネータ / 質問パターン見直し (#41) #365
@@ -306,6 +306,10 @@ const chooseQuestion = ({
|
|||||||
const scoredPosts = posts
|
const scoredPosts = posts
|
||||||
.map (post => ({ post, score: scores.get (post.id) ?? 0 }))
|
.map (post => ({ post, score: scores.get (post.id) ?? 0 }))
|
||||||
.sort ((a, b) => b.score - a.score)
|
.sort ((a, b) => b.score - a.score)
|
||||||
|
const topScore = scoredPosts[0]?.score ?? 0
|
||||||
|
const nearTopCandidates = scoredPosts.filter (item => topScore - item.score <= 2)
|
||||||
|
const focusCandidates =
|
||||||
|
nearTopCandidates.length >= 2 && nearTopCandidates.length <= 8 ? nearTopCandidates : []
|
||||||
|
|
||||||
const signatureFor = (
|
const signatureFor = (
|
||||||
question: GekanatorQuestion,
|
question: GekanatorQuestion,
|
||||||
@@ -333,6 +337,7 @@ const chooseQuestion = ({
|
|||||||
const rank = (
|
const rank = (
|
||||||
questionsToRank: GekanatorQuestion[],
|
questionsToRank: GekanatorQuestion[],
|
||||||
candidates: { post: Post; score: number }[],
|
candidates: { post: Post; score: number }[],
|
||||||
|
focusCandidates: { post: Post; score: number }[],
|
||||||
) => {
|
) => {
|
||||||
const redundant = redundantSignatures (candidates)
|
const redundant = redundantSignatures (candidates)
|
||||||
const nonTagCount =
|
const nonTagCount =
|
||||||
@@ -349,25 +354,49 @@ const chooseQuestion = ({
|
|||||||
if (yes === 0 || no === 0)
|
if (yes === 0 || no === 0)
|
||||||
return null
|
return null
|
||||||
|
|
||||||
|
const focusSignature = signatureFor (question, focusCandidates)
|
||||||
|
const focusYes = focusSignature.split ('').filter (value => value === '1').length
|
||||||
|
const focusNo = focusCandidates.length - focusYes
|
||||||
|
const separatesFocus = focusCandidates.length >= 2 && focusYes > 0 && focusNo > 0
|
||||||
|
|
||||||
const splitScore = Math.abs (candidates.length / 2 - yes)
|
const splitScore = Math.abs (candidates.length / 2 - yes)
|
||||||
|
const focusSplitScore = focusCandidates.length >= 2
|
||||||
|
? Math.abs (focusCandidates.length / 2 - focusYes)
|
||||||
|
: 0
|
||||||
const tagPenalty = question.kind === 'tag' && nonTagCount < 4 ? 12 : 0
|
const tagPenalty = question.kind === 'tag' && nonTagCount < 4 ? 12 : 0
|
||||||
const minSide = candidates.length < 10 ? 1 : Math.max (3, candidates.length * .08)
|
const minSide = candidates.length < 10 ? 1 : Math.max (3, candidates.length * .08)
|
||||||
const narrowPenalty = yes < minSide || no < minSide ? candidates.length : 0
|
const narrowPenalty = yes < minSide || no < minSide ? candidates.length : 0
|
||||||
|
const focusPenalty =
|
||||||
|
focusCandidates.length >= 2 && !(separatesFocus) ? candidates.length * 10 : 0
|
||||||
|
|
||||||
return { question,
|
return { question,
|
||||||
score: splitScore + tagPenalty + narrowPenalty,
|
score: focusPenalty
|
||||||
narrow: narrowPenalty > 0 }
|
+ focusSplitScore * 20
|
||||||
|
+ splitScore
|
||||||
|
+ tagPenalty
|
||||||
|
+ narrowPenalty,
|
||||||
|
narrow: narrowPenalty > 0,
|
||||||
|
separatesFocus }
|
||||||
})
|
})
|
||||||
.filter ((item): item is {
|
.filter ((item): item is {
|
||||||
question: GekanatorQuestion
|
question: GekanatorQuestion
|
||||||
score: number
|
score: number
|
||||||
narrow: boolean } => item !== null && Number.isFinite (item.score))
|
narrow: boolean
|
||||||
|
separatesFocus: boolean } => item !== null && Number.isFinite (item.score))
|
||||||
.sort ((a, b) => a.score - b.score)
|
.sort ((a, b) => a.score - b.score)
|
||||||
}
|
}
|
||||||
|
|
||||||
const unansweredQuestions =
|
const unansweredQuestions =
|
||||||
questions.filter (question => !(askedIds.has (question.id)))
|
questions.filter (question => !(askedIds.has (question.id)))
|
||||||
const ranked = rank (unansweredQuestions, scoredPosts)
|
const ranked = rank (unansweredQuestions, scoredPosts, focusCandidates)
|
||||||
|
|
||||||
|
if (focusCandidates.length >= 2)
|
||||||
|
return (
|
||||||
|
ranked.find (item => item.separatesFocus && !(item.narrow))
|
||||||
|
?? ranked.find (item => item.separatesFocus)
|
||||||
|
?? ranked.find (item => !(item.narrow))
|
||||||
|
?? ranked[0]
|
||||||
|
)?.question ?? null
|
||||||
|
|
||||||
return (ranked.find (item => !(item.narrow)) ?? ranked[0])?.question ?? null
|
return (ranked.find (item => !(item.narrow)) ?? ranked[0])?.question ?? null
|
||||||
}
|
}
|
||||||
|
|||||||
新しい課題から参照
ユーザをブロックする