@@ -430,17 +548,17 @@
Members:
- {#each groupDoc.data.participants as participant}
+ {#each groupDoc.data.participants as participant, index}
-
{#if participant === user.uid}
- You
+ You{index === 0 ? ' (Leader)' : ''}
{:else}
{#await getUser(participant)}
載入中...
{:then profile}
- {profile.displayName}
+ {profile.displayName}{index === 0 ? ' (Leader)' : ''}
{:catch}
未知使用者
{/await}
@@ -508,11 +626,32 @@
{:else if $session?.status === 'group'}
-
+ {#if groupStatus === 'discussion' && !loadingGroupSummary}
+
+ {:else if groupStatus === 'summarize' || loadingGroupSummary}
+ {#if groupDoc}
+
+ {/if}
+ {:else if groupStatus === 'end'}
+ {#if groupDoc}
+
+ {/if}
+ {/if}
{/if}
diff --git a/src/lib/schema/group.ts b/src/lib/schema/group.ts
index 8fa5f85..21d9eb9 100644
--- a/src/lib/schema/group.ts
+++ b/src/lib/schema/group.ts
@@ -14,6 +14,8 @@ export const GroupSchema = z.object({
audio: z.string().nullable() // to find the raw file
})
),
+ updatedAt: z.date().nullable(),
+ status: z.enum(['discussion', 'summarize', 'end']).default('discussion'),
summary: z.string().nullable(), // lock on stage 2 finalize transaction
keywords: z.record(z.string(), z.number().min(1).max(5))
});
diff --git a/src/lib/server/llm.ts b/src/lib/server/llm.ts
index bad2698..9319d4b 100644
--- a/src/lib/server/llm.ts
+++ b/src/lib/server/llm.ts
@@ -349,9 +349,10 @@ export async function summarizeConcepts(
export async function summarizeGroupOpinions(
student_opinion: StudentSpeak[]
-): Promise<{ success: boolean; summary: string; error?: string }> {
+): Promise<{ success: boolean; summary: string; keywords: string[]; error?: string }> {
try {
const formatted_opinions = student_opinion
+ .filter((opinion) => opinion.role !== '摘要小幫手')
.map((opinion) => `${opinion.role}: ${opinion.content}`)
.join('\n');
@@ -374,13 +375,15 @@ export async function summarizeGroupOpinions(
return {
success: true,
- summary: message.group_summary
+ summary: message.group_summary,
+ keywords: message.group_key_points
};
} catch (error) {
console.error('Error in summarizeGroupOpinions:', error);
return {
success: false,
summary: '',
+ keywords: [],
error: 'Failed to summarize group opinions'
};
}
diff --git a/src/routes/api/session/[id]/group/[group_number]/discussions/add/+server.ts b/src/routes/api/session/[id]/group/[group_number]/discussions/add/+server.ts
index ed23a20..7a966b1 100644
--- a/src/routes/api/session/[id]/group/[group_number]/discussions/add/+server.ts
+++ b/src/routes/api/session/[id]/group/[group_number]/discussions/add/+server.ts
@@ -41,7 +41,8 @@ export const POST: RequestHandler = async ({ request, params, locals }) => {
speaker: speaker,
audio: audio
}
- ]
+ ],
+ updatedAt: new Date()
});
});
diff --git a/src/routes/api/session/[id]/group/[group_number]/discussions/end/+server.ts b/src/routes/api/session/[id]/group/[group_number]/discussions/end/+server.ts
new file mode 100644
index 0000000..8293276
--- /dev/null
+++ b/src/routes/api/session/[id]/group/[group_number]/discussions/end/+server.ts
@@ -0,0 +1,25 @@
+import { adminDb } from '$lib/server/firebase';
+import { error, json } from '@sveltejs/kit';
+
+export async function POST({ params, locals }) {
+ if (!locals.user) {
+ throw error(401, '未經授權');
+ }
+
+ try {
+ const groupRef = adminDb
+ .collection('sessions')
+ .doc(params.id)
+ .collection('groups')
+ .doc(params.group_number);
+
+ await groupRef.update({
+ status: 'end'
+ });
+
+ return json({ status: 'success' });
+ } catch (e) {
+ console.error('Error ending group summarize phase:', e);
+ throw error(500, '無法結束群組總結階段');
+ }
+}
diff --git a/src/routes/api/session/[id]/group/[group_number]/discussions/summary/+server.ts b/src/routes/api/session/[id]/group/[group_number]/discussions/summary/+server.ts
index eea1860..b42ca03 100644
--- a/src/routes/api/session/[id]/group/[group_number]/discussions/summary/+server.ts
+++ b/src/routes/api/session/[id]/group/[group_number]/discussions/summary/+server.ts
@@ -21,6 +21,11 @@ export const GET: RequestHandler = async ({ params, locals }) => {
const group_ref = getGroupRef(id, group_number);
const { discussions } = await getGroupData(group_ref);
+
+ group_ref.update({
+ status: 'summarize'
+ });
+
const student_opinions = discussion2StudentSpeak(discussions);
const response = await summarizeGroupOpinions(student_opinions);
@@ -29,7 +34,8 @@ export const GET: RequestHandler = async ({ params, locals }) => {
}
group_ref.update({
- group_summary: response.summary
+ summary: response.summary,
+ keywords: response.keywords
});
return json({ success: true }, { status: 200 });
@@ -43,7 +49,8 @@ export const GET: RequestHandler = async ({ params, locals }) => {
// PUT /api/session/[id]/group/[group_number]/discussions/summary/+server
// Request data format
const requestDataFormat = z.object({
- updated_summary: z.string()
+ updated_summary: z.string(),
+ keywords: z.array(z.string())
});
export const PUT: RequestHandler = async ({ request, params, locals }) => {
@@ -57,10 +64,12 @@ export const PUT: RequestHandler = async ({ request, params, locals }) => {
return json({ error: 'Missing parameters' }, { status: 400 });
}
- const { updated_summary } = await getRequestData(request);
+ const { updated_summary, keywords } = await getRequestData(request);
const group_ref = getGroupRef(id, group_number);
+ console.log('Updating group summary...', updated_summary, keywords);
group_ref.update({
- group_summary: updated_summary
+ summary: updated_summary,
+ keywords: keywords
});
return json({ success: true }, { status: 200 });