このコミットが含まれているのは:
+45
-11
@@ -22,6 +22,12 @@ export type GekanatorQuestionKind =
|
||||
| 'title'
|
||||
| 'original_date'
|
||||
|
||||
export type GekanatorQuestionSource =
|
||||
| 'default'
|
||||
| 'user_suggested'
|
||||
| 'ai_generated'
|
||||
| 'admin_curated'
|
||||
|
||||
export type GekanatorQuestionCondition =
|
||||
| { type: 'tag'; key: string }
|
||||
| { type: 'source'; host: string }
|
||||
@@ -32,17 +38,21 @@ export type GekanatorQuestionCondition =
|
||||
| { type: 'title-has-ascii' }
|
||||
|
||||
export type StoredGekanatorQuestion = {
|
||||
id: string
|
||||
text: string
|
||||
kind: GekanatorQuestionKind
|
||||
condition: GekanatorQuestionCondition }
|
||||
id: string
|
||||
text: string
|
||||
kind: GekanatorQuestionKind
|
||||
condition: GekanatorQuestionCondition
|
||||
source?: GekanatorQuestionSource
|
||||
priorityWeight?: number }
|
||||
|
||||
export type GekanatorQuestion = {
|
||||
id: string
|
||||
text: string
|
||||
kind: GekanatorQuestionKind
|
||||
condition: GekanatorQuestionCondition
|
||||
test: (post: Post) => boolean }
|
||||
id: string
|
||||
text: string
|
||||
kind: GekanatorQuestionKind
|
||||
condition: GekanatorQuestionCondition
|
||||
source: GekanatorQuestionSource
|
||||
priorityWeight: number
|
||||
test: (post: Post) => boolean }
|
||||
|
||||
const countBy = <T extends string | number> (values: T[]): Map<T, number> => {
|
||||
const counts = new Map<T, number> ()
|
||||
@@ -188,6 +198,8 @@ export const restoreGekanatorQuestion = (
|
||||
question: StoredGekanatorQuestion,
|
||||
): GekanatorQuestion => ({
|
||||
...question,
|
||||
source: question.source ?? 'default',
|
||||
priorityWeight: question.priorityWeight ?? 1,
|
||||
test: (post: Post) => questionMatches (post, question.condition) })
|
||||
|
||||
|
||||
@@ -197,7 +209,9 @@ export const storeGekanatorQuestion = (
|
||||
id: question.id,
|
||||
text: question.text,
|
||||
kind: question.kind,
|
||||
condition: question.condition })
|
||||
condition: question.condition,
|
||||
source: question.source,
|
||||
priorityWeight: question.priorityWeight })
|
||||
|
||||
|
||||
export const fetchGekanatorPosts = async (): Promise<Post[]> => {
|
||||
@@ -206,6 +220,12 @@ export const fetchGekanatorPosts = async (): Promise<Post[]> => {
|
||||
}
|
||||
|
||||
|
||||
export const fetchGekanatorQuestions = async (): Promise<StoredGekanatorQuestion[]> => {
|
||||
const data = await apiGet<{ questions: StoredGekanatorQuestion[] }> ('/gekanator/questions')
|
||||
return data.questions
|
||||
}
|
||||
|
||||
|
||||
export const buildGekanatorQuestions = (posts: Post[]): GekanatorQuestion[] => {
|
||||
const tagCounts = countBy (posts.flatMap (post =>
|
||||
post.tags
|
||||
@@ -248,6 +268,8 @@ export const buildGekanatorQuestions = (posts: Post[]): GekanatorQuestion[] => {
|
||||
text: tagQuestionText (category, label),
|
||||
kind: 'tag' as const,
|
||||
condition: { type: 'tag' as const, key: String (key) },
|
||||
source: 'default' as const,
|
||||
priorityWeight: 1,
|
||||
test: (post: Post) => questionableTag (post, String (key)) }
|
||||
})
|
||||
|
||||
@@ -259,6 +281,8 @@ export const buildGekanatorQuestions = (posts: Post[]): GekanatorQuestion[] => {
|
||||
text: `${ host } の投稿を思ひ浮かべてゐる?`,
|
||||
kind: 'source' as const,
|
||||
condition: { type: 'source' as const, host },
|
||||
source: 'default' as const,
|
||||
priorityWeight: 1,
|
||||
test: (post: Post) => hostOf (post) === host }))
|
||||
|
||||
const originalYearQuestions = usefulEntries (originalYears)
|
||||
@@ -269,6 +293,8 @@ export const buildGekanatorQuestions = (posts: Post[]): GekanatorQuestion[] => {
|
||||
text: `オリジナルの投稿年は ${ year } 年?`,
|
||||
kind: 'original_date' as const,
|
||||
condition: { type: 'original-year' as const, year },
|
||||
source: 'default' as const,
|
||||
priorityWeight: 1,
|
||||
test: (post: Post) => originalYearOf (post) === year }))
|
||||
|
||||
const originalMonthQuestions = usefulEntries (originalMonths)
|
||||
@@ -279,6 +305,8 @@ export const buildGekanatorQuestions = (posts: Post[]): GekanatorQuestion[] => {
|
||||
text: `オリジナルの投稿月は ${ month } 月?`,
|
||||
kind: 'original_date' as const,
|
||||
condition: { type: 'original-month' as const, month },
|
||||
source: 'default' as const,
|
||||
priorityWeight: 1,
|
||||
test: (post: Post) => originalMonthOf (post) === month }))
|
||||
|
||||
const originalMonthDayQuestions = usefulEntries (originalMonthDays)
|
||||
@@ -292,6 +320,8 @@ export const buildGekanatorQuestions = (posts: Post[]): GekanatorQuestion[] => {
|
||||
text: `オリジナルの投稿日は ${ month } 月 ${ day } 日?`,
|
||||
kind: 'original_date' as const,
|
||||
condition: { type: 'original-month-day' as const, monthDay: String (monthDay) },
|
||||
source: 'default' as const,
|
||||
priorityWeight: 1,
|
||||
test: (post: Post) => originalMonthDayOf (post) === monthDay }
|
||||
})
|
||||
|
||||
@@ -303,12 +333,16 @@ export const buildGekanatorQuestions = (posts: Post[]): GekanatorQuestion[] => {
|
||||
condition: {
|
||||
type: 'title-length-greater-than' as const,
|
||||
length: titleLengthMedian },
|
||||
source: 'default' as const,
|
||||
priorityWeight: 1,
|
||||
test: (post: Post) => (post.title?.length ?? 0) > titleLengthMedian },
|
||||
{
|
||||
id: 'title:ascii',
|
||||
text: '題名に英数字が混じってゐる?',
|
||||
kind: 'title' as const,
|
||||
condition: { type: 'title-has-ascii' as const },
|
||||
source: 'default' as const,
|
||||
priorityWeight: 1,
|
||||
test: (post: Post) => /[A-Za-z0-9]/.test (post.title ?? '') }]
|
||||
.filter (question => {
|
||||
const yes = posts.filter (post => question.test (post)).length
|
||||
@@ -354,7 +388,7 @@ export const saveGekanatorQuestionSuggestion = async ({
|
||||
gekanatorGameId: number
|
||||
questionText: string
|
||||
answer: GekanatorAnswerValue
|
||||
}): Promise<{ id: number }> =>
|
||||
}): Promise<{ id: number; count: number }> =>
|
||||
await apiPost ('/gekanator/question_suggestions', {
|
||||
gekanator_game_id: gekanatorGameId,
|
||||
question_text: questionText,
|
||||
|
||||
新しい課題から参照
ユーザをブロックする