computer-scienceangular-roadmapbackend-roadmapblockchain-roadmapdba-roadmapdeveloper-roadmapdevops-roadmapfrontend-roadmapgo-roadmaphactoberfestjava-roadmapjavascript-roadmapnodejs-roadmappython-roadmapqa-roadmapreact-roadmaproadmapstudy-planvue-roadmapweb3-roadmap
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
169 lines
3.7 KiB
169 lines
3.7 KiB
export const IS_KEY_ONLY_ROADMAP_GENERATION = false; |
|
|
|
type Lesson = string; |
|
|
|
type Module = { |
|
title: string; |
|
lessons: Lesson[]; |
|
}; |
|
|
|
export type AiCourse = { |
|
title: string; |
|
modules: Module[]; |
|
difficulty: string; |
|
}; |
|
|
|
export function generateAiCourseStructure( |
|
data: string, |
|
): Omit<AiCourse, 'difficulty'> { |
|
const lines = data.split('\n'); |
|
let title = ''; |
|
const modules: Module[] = []; |
|
let currentModule: Module | null = null; |
|
|
|
for (let i = 0; i < lines.length; i++) { |
|
const line = lines[i].trim(); |
|
|
|
if (i === 0 && line.startsWith('#')) { |
|
// First line is the title |
|
title = line.replace('#', '').trim(); |
|
} else if (line.startsWith('## ')) { |
|
// New module |
|
if (currentModule) { |
|
modules.push(currentModule); |
|
} |
|
currentModule = { |
|
title: line.replace('## ', ''), |
|
lessons: [], |
|
}; |
|
// Removed auto-expand code to keep modules collapsed by default |
|
} else if (line.startsWith('- ') && currentModule) { |
|
// Lesson within current module |
|
currentModule.lessons.push(line.replace('- ', '')); |
|
} |
|
} |
|
|
|
// Add the last module if it exists |
|
if (currentModule) { |
|
modules.push(currentModule); |
|
} |
|
|
|
return { |
|
title, |
|
modules, |
|
}; |
|
} |
|
|
|
const NEW_LINE = '\n'.charCodeAt(0); |
|
|
|
export async function readAIRoadmapStream( |
|
reader: ReadableStreamDefaultReader<Uint8Array>, |
|
{ |
|
onStream, |
|
onStreamEnd, |
|
}: { |
|
onStream?: (roadmap: string) => void; |
|
onStreamEnd?: (roadmap: string) => void; |
|
}, |
|
) { |
|
const decoder = new TextDecoder('utf-8'); |
|
let result = ''; |
|
|
|
while (true) { |
|
const { value, done } = await reader.read(); |
|
if (done) { |
|
break; |
|
} |
|
|
|
// We will call the renderRoadmap callback whenever we encounter |
|
// a new line with the result until the new line |
|
// otherwise, we will keep appending the result to the previous result |
|
if (value) { |
|
let start = 0; |
|
for (let i = 0; i < value.length; i++) { |
|
if (value[i] === NEW_LINE) { |
|
result += decoder.decode(value.slice(start, i + 1)); |
|
onStream?.(result); |
|
start = i + 1; |
|
} |
|
} |
|
if (start < value.length) { |
|
result += decoder.decode(value.slice(start)); |
|
} |
|
} |
|
} |
|
|
|
onStream?.(result); |
|
onStreamEnd?.(result); |
|
reader.releaseLock(); |
|
} |
|
|
|
export async function readAIRoadmapContentStream( |
|
reader: ReadableStreamDefaultReader<Uint8Array>, |
|
{ |
|
onStream, |
|
onStreamEnd, |
|
}: { |
|
onStream?: (roadmap: string) => void; |
|
onStreamEnd?: (roadmap: string) => void; |
|
}, |
|
) { |
|
const decoder = new TextDecoder('utf-8'); |
|
let result = ''; |
|
|
|
while (true) { |
|
const { value, done } = await reader.read(); |
|
if (done) { |
|
break; |
|
} |
|
|
|
if (value) { |
|
result += decoder.decode(value); |
|
onStream?.(result); |
|
} |
|
} |
|
|
|
onStream?.(result); |
|
onStreamEnd?.(result); |
|
reader.releaseLock(); |
|
} |
|
|
|
export async function readStream( |
|
reader: ReadableStreamDefaultReader<Uint8Array>, |
|
{ |
|
onStream, |
|
onStreamEnd, |
|
}: { |
|
onStream?: (course: string) => void; |
|
onStreamEnd?: (course: string) => void; |
|
}, |
|
) { |
|
const decoder = new TextDecoder('utf-8'); |
|
let result = ''; |
|
|
|
while (true) { |
|
const { value, done } = await reader.read(); |
|
if (done) { |
|
break; |
|
} |
|
|
|
// Process the stream data as it comes in |
|
if (value) { |
|
let start = 0; |
|
for (let i = 0; i < value.length; i++) { |
|
if (value[i] === NEW_LINE) { |
|
result += decoder.decode(value.slice(start, i + 1)); |
|
onStream?.(result); |
|
start = i + 1; |
|
} |
|
} |
|
if (start < value.length) { |
|
result += decoder.decode(value.slice(start)); |
|
} |
|
} |
|
} |
|
|
|
onStream?.(result); |
|
onStreamEnd?.(result); |
|
reader.releaseLock(); |
|
}
|
|
|