Reviewed-on: #377 Co-authored-by: miteruzo <miteruzo@naver.com> Co-committed-by: miteruzo <miteruzo@naver.com>
このコミットはPull リクエスト #377 でマージされました.
このコミットが含まれているのは:
@@ -1,15 +1,21 @@
|
||||
import { expectedAnswerForQuestion } from '@/lib/gekanator'
|
||||
import { isLearnedSemanticQuestion,
|
||||
learnedSemanticSideForPost } from '@/lib/gekanator'
|
||||
|
||||
import type { GekanatorAnswerLog, GekanatorAnswerValue, GekanatorQuestion } from '@/lib/gekanator'
|
||||
import type { Post } from '@/types'
|
||||
|
||||
export type RecoveredCandidatePost = {
|
||||
postId: number
|
||||
answerCountAtRecovery: number }
|
||||
answerCountAtRecovery: number
|
||||
scoreAtRecovery: number }
|
||||
|
||||
export type RecoveredCandidateState = {
|
||||
answerCountAtRecovery: number
|
||||
scoreAtRecovery: number }
|
||||
|
||||
|
||||
const questionIsFactLikeForHardFiltering = (question: GekanatorQuestion): boolean =>
|
||||
!(question.kind === 'post_similarity'
|
||||
const questionSupportsAnswerBasedHardFiltering = (question: GekanatorQuestion): boolean =>
|
||||
!(isLearnedSemanticQuestion (question)
|
||||
|| (question.kind === 'tag'
|
||||
&& question.condition.type === 'tag'
|
||||
&& !(question.condition.key.startsWith ('nico:'))))
|
||||
@@ -26,7 +32,7 @@ export const candidatePostsFor = (
|
||||
answers: GekanatorAnswerLog[]
|
||||
softenedQuestionIds: Set<string>
|
||||
rejectedPostIds: Set<number>
|
||||
recoveredCandidatePosts: Map<number, number> },
|
||||
recoveredCandidatePosts: Map<number, RecoveredCandidateState> },
|
||||
): Post[] => {
|
||||
const questionById = new Map (questions.map (question => [question.id, question]))
|
||||
|
||||
@@ -34,10 +40,10 @@ export const candidatePostsFor = (
|
||||
if (rejectedPostIds.has (post.id))
|
||||
return false
|
||||
|
||||
const answerCountAtRecovery = recoveredCandidatePosts.get (post.id)
|
||||
const recoveredCandidate = recoveredCandidatePosts.get (post.id)
|
||||
|
||||
return answers.every ((answer, index) => {
|
||||
if (answerCountAtRecovery != null && index < answerCountAtRecovery)
|
||||
if (recoveredCandidate != null && index < recoveredCandidate.answerCountAtRecovery)
|
||||
return true
|
||||
|
||||
if (softenedQuestionIds.has (answer.questionId))
|
||||
@@ -46,7 +52,7 @@ export const candidatePostsFor = (
|
||||
const question = questionById.get (answer.questionId)
|
||||
if (!(question))
|
||||
return true
|
||||
if (!(questionIsFactLikeForHardFiltering (question)))
|
||||
if (!(questionSupportsAnswerBasedHardFiltering (question)))
|
||||
return true
|
||||
|
||||
switch (answer.answer)
|
||||
@@ -54,8 +60,10 @@ export const candidatePostsFor = (
|
||||
case 'yes':
|
||||
case 'no':
|
||||
{
|
||||
const expected = expectedAnswerForQuestion (question, post)
|
||||
return expected === null || expected === 'unknown' || expected === answer.answer
|
||||
const expected = learnedSemanticSideForPost (question, post)
|
||||
return expected === 'unknown'
|
||||
|| (answer.answer === 'yes' && expected === 'positive')
|
||||
|| (answer.answer === 'no' && expected === 'negative')
|
||||
}
|
||||
default:
|
||||
return true
|
||||
@@ -70,15 +78,17 @@ export const hardFilteredPostsForAnswer = (
|
||||
question: GekanatorQuestion
|
||||
answer: GekanatorAnswerValue },
|
||||
): Post[] => {
|
||||
if (!(questionIsFactLikeForHardFiltering (question)))
|
||||
if (!(questionSupportsAnswerBasedHardFiltering (question)))
|
||||
return posts
|
||||
|
||||
if (!(answer === 'yes' || answer === 'no'))
|
||||
return posts
|
||||
|
||||
return posts.filter (post => {
|
||||
const expected = expectedAnswerForQuestion (question, post)
|
||||
return expected == null || expected === 'unknown' || expected === answer
|
||||
const side = learnedSemanticSideForPost (question, post)
|
||||
return side === 'unknown'
|
||||
|| (answer === 'yes' && side === 'positive')
|
||||
|| (answer === 'no' && side === 'negative')
|
||||
})
|
||||
}
|
||||
|
||||
@@ -112,11 +122,11 @@ export const recoverCandidatePosts = (
|
||||
recoveryStepCount }: { posts: Post[]
|
||||
scores: Map<number, number>
|
||||
rejectedPostIds: Set<number>
|
||||
recoveredCandidatePosts: Map<number, number>
|
||||
recoveredCandidatePosts: Map<number, RecoveredCandidateState>
|
||||
eligiblePostIds: Set<number>
|
||||
answerCountAtRecovery: number
|
||||
recoveryStepCount: number },
|
||||
): { recoveredCandidatePosts: Map<number, number>
|
||||
): { recoveredCandidatePosts: Map<number, RecoveredCandidateState>
|
||||
recoveryStepCount: number } | null => {
|
||||
const recovered = new Map (recoveredCandidatePosts)
|
||||
const targetSize = nextRecoveryTargetSize (recoveryStepCount)
|
||||
@@ -140,7 +150,9 @@ export const recoverCandidatePosts = (
|
||||
if (candidates.length === 0)
|
||||
return null
|
||||
|
||||
candidates.forEach (post => recovered.set (post.id, answerCountAtRecovery))
|
||||
candidates.forEach (post => recovered.set (post.id, {
|
||||
answerCountAtRecovery,
|
||||
scoreAtRecovery: scores.get (post.id) ?? 0 }))
|
||||
|
||||
return { recoveredCandidatePosts: recovered,
|
||||
recoveryStepCount: recoveryStepCount + 1 }
|
||||
|
||||
新しい課題から参照
ユーザをブロックする