From 7e7e0ad08b2d5c2421fb9d0b06179146371446ee Mon Sep 17 00:00:00 2001 From: Ben Carter Date: Mon, 18 Mar 2024 23:36:30 -0400 Subject: [PATCH] Added interface --- src/aidocs-generator-interfaces.ts | 173 +++++++++++++++++++++++++++++ src/player.ts | 99 +++++++++++++++++ src/wow.api.ts | 107 ++++++++++++++++++ 3 files changed, 379 insertions(+) create mode 100644 src/aidocs-generator-interfaces.ts create mode 100644 src/player.ts create mode 100644 src/wow.api.ts diff --git a/src/aidocs-generator-interfaces.ts b/src/aidocs-generator-interfaces.ts new file mode 100644 index 0000000..1be8b00 --- /dev/null +++ b/src/aidocs-generator-interfaces.ts @@ -0,0 +1,173 @@ +import {OpenAI } from "openai"; +import Anthropic from "@anthropic-ai/sdk"; +import * as fs from "fs"; +import * as ts from "typescript"; +import * as dotenv from "dotenv"; +import { Command } from 'commander'; +const program = new Command(); + + +dotenv.config(); + +const openai = new OpenAI({ + apiKey: process.env.OPENAI_API_KEY, +}); + +const claude = new Anthropic({ + apiKey: process.env.CLAUDE_API_KEY +}); + +type ClassMethod = { + className: string; + methodName: string; + methodSignature: string; + comments: string; // Add this line to include comments +} + +type ParseSettings = { + className: string; + file: string; + exclude?: string[]; + include?: string[]; +} + +function parseDeclarations(settings: ParseSettings): ClassMethod[] { + const filePath = settings.file; + + const fileContent = fs.readFileSync(filePath, "utf8"); + const sourceFile = ts.createSourceFile( + filePath, + fileContent, + ts.ScriptTarget.Latest, + true + ); + let classMethods: ClassMethod[] = []; + + function getLeadingComments(node: ts.Node): string { + const fullText = node.getFullText(sourceFile); + const comments = ts.getLeadingCommentRanges(fullText, 0); + + if (!comments) return ''; + let commentText = ''; + comments.forEach((comment) => { + commentText += fullText.substring(comment.pos, comment.end) + '\n'; + }); + return commentText.trim(); + } + + function visit(node: ts.Node) { + if ((ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node)) && node.name) { + + if (settings.className && node.name.text !== settings.className) { + return; + } + + const className = node.name.text; + node.members.forEach((member) => { + if (ts.isMethodSignature(member) || ts.isMethodDeclaration(member)) { + if (member.name) { + let methodName = member.name.getText(sourceFile); + + if (settings.exclude && settings.exclude.includes(methodName)) { + return; + } + + if (settings.include && !settings.include.includes(methodName)) { + return; + } + + let methodSignature = member.getText(sourceFile); + let comments = getLeadingComments(member); + classMethods.push({ className, methodName, methodSignature, comments }); + } + } + }); + } + ts.forEachChild(node, visit); + } + + visit(sourceFile); + return classMethods; +} + + +type AiModel = 'claude' | 'gpt3' | 'gpt4' + +async function createDocs(classMethods: ClassMethod[], aiModel: AiModel): Promise { + const fewShotExample = fs.readFileSync(`${__dirname}/wow.api.ts`); + + let currentClass = ''; + for (const { className, methodName, methodSignature, comments } of classMethods) { + if (currentClass !== className) { + // When we encounter a new class, we reset currentClass to the new className + currentClass = className; + } + + let content: string; + let response: any; + const prompt = `${fewShotExample}\n\n Use the provided examples of documenting methods and knowneldge of mod-eluna, azerothcore, create markdown docs for this method: \n\n declare class ${className} {\n Inline Code Comment: ${comments} Method: ${methodName} MethodSignature ${methodSignature}\n} the examples should be not be too simple, and have 10-20 lines`; + switch(aiModel) { + case 'gpt3': + response = await openai.chat.completions.create({ + model: "gpt-3.5-turbo", + messages: [{ role: 'user', content: prompt}], + }); + + if(typeof response.choices[0].message.content == 'string') { + content = response.choices[0].message.content; + } + break; + case 'gpt4': + response = await openai.chat.completions.create({ + model: "gpt-4-turbo-preview", + messages: [{ role: 'user', content: prompt}], + }); + if(typeof response.choices[0].message.content == 'string') { + content = response.choices[0].message.content; + } + break; + case 'claude': + response = await claude.messages.create({ + model: 'claude-3-opus-20240229', + max_tokens: 2000, + messages: [{ role: "user", content: prompt}] + }); + if(typeof response.content[0].text == 'string') { + content = response.content[0].text; + } + break; + } + + + console.log(`writing documentation for ${className}.${methodName}`); + const documentation = content.replace(`filename: ${className.toLowerCase()}.md\n`, ''); + // Ensure directory exists + const dir = './docs/wowapi/classes'; + if (!fs.existsSync(dir)){ + fs.mkdirSync(dir); + } + // Write to a separate markdown file for each class + fs.appendFileSync(`${dir}/${className}.md`, documentation + '\n\n'); + } + } + + ( async() => { + + program + .option('-m, --model ', 'The AI model to use for documentation generation. Options are gpt3, gpt4, claude', 'gpt3') + .requiredOption('-f, --file ', 'The file to parse for class methods') + .requiredOption('-c, --class ', 'Which classe to process from the file') + .option('-e, --exclude ', 'The file to parse for class methods') + .option('-i, --include ', 'The file to parse for class methods') + program.parse(); + + const options = program.opts(); + const classOutputs = parseDeclarations({ + file: options.file, + className: options.class, + exclude: options.exclude ? options.exclude.split(',') : undefined, + include: options.include ? options.include.split(',') : undefined + }); + console.log(classOutputs); + await createDocs(classOutputs, options.model); + })(); diff --git a/src/player.ts b/src/player.ts new file mode 100644 index 0000000..c2c9800 --- /dev/null +++ b/src/player.ts @@ -0,0 +1,99 @@ +Here is an example of how to convert TypeScript Class definitions into +readme documentation in a consistent format based on how it will be used +to build mods for mod-eluna on Azerothcore. + +Given the following TypeScript class definition for the Player class: + +declare class Player extends Unit { + /** + * Adds combo points to the [Player] + */ + AddComboPoints(target: Unit, count: number): void; + + /** + * Adds the given amount of the specified item entry to the player. + */ + AddItem(entry: number, itemCount?: number): Item; + + /** + + */ + AddLifetimeKills(): void; + + /** + * Tries to add the given quest entry for the [Player]. + */ + AddQuest(entry: number): void; + + /** + * Advances all of the [Player]s skills to the amount specified + */ + AdvanceAllSkills(skillStep: number): void; + + /** + * Advances a [Player]s specific skill to the amount specified + */ + AdvanceSkill(skillId: number, skillStep: number): void; + + /** + * Advances all of the [Player]s weapon skills to the maximum amount available + */ + AdvanceSkillsToMax(): void; + + /** + * Completes the [Quest] if a [Quest] area is explored, or completes the [Quest] + */ + AreaExploredOrEventHappens(quest: number): void; + + /** + * Returns 'true' if the [Player] can block incomming attacks, 'false' otherwise. + */ + CanBlock(): boolean; + + /** + * Returns 'true' if the [Player] satisfies all requirements to complete the quest entry. + */ + CanCompleteQuest(entry: number): boolean; +} +## AddComboPoints +If the player is a rogue or druid, this method will add combo points to the player +based on the target and the count of combo points to add. + +### Parameters +* enemy: [Unit](./unit.md) - Unit to apply combo points to +* count: number - The number of combo points to apply + +### Example Usage: +Simple script to start a rogue/druid with an advantage. +```typescript +const onPlayerEnter: player_event_on_enter_combat = (event: number, player: Player, enemy: Unit): void => { + + player.AddComboPoints(enemy, 5); + +} +RegisterPlayerEvent(PlayerEvents.PLAYER_EVENT_ON_ENTER_COMBAT, (...args) => onPlayerEnter(...args)); +``` +## AddItem +Give the player an item based on the item entry. These items can be referenced in World Database item_template. +for more information about items you can find more information here: https://www.azerothcore.org/wiki/item_template. +Items will be added to the current bag inventory if there is space. + +### Parameters
+entry: number - Item Entry Id from item_template table +count: number - number of items to grant (Items that exceed unique counts or limits to amount will fail) +### Returns +item: [Item](./item.md) - The item(s) that was given to the player. +### Example Usage: +Grant bonus Badges of Justice +const BADGE_OF_JUSTICE_ENTRY = 29434; +const BADGE_OF_JUSTICE_BONUS = 2; + +const LootToken: player_event_on_loot_item = (event: number, player: Player, item: Item) => { + + if(item.GetEntry() == BADGE_OF_JUSTICE_ENTRY) { + player.AddItem(BADGE_OF_JUSTICE_ENTRY, BADGE_OF_JUSTICE_BONUS); + } +} + +RegisterPlayerEvent(PlayerEvents.PLAYER_EVENT_ON_LOOT_ITEM, (...args) => LootToken(...args)); + diff --git a/src/wow.api.ts b/src/wow.api.ts new file mode 100644 index 0000000..4e5bfa1 --- /dev/null +++ b/src/wow.api.ts @@ -0,0 +1,107 @@ +import { isReturnStatement } from "typescript" + +Here is an example of how to convert TypeScript Class definitions into +readme documentation in a consistent format based on how it will be used +to build AIO plugins which is similar to World of Warcraft AddOns, which reference +the World of Warcraft API that can be found here: https://wowpedia.fandom.com/wiki/World_of_Warcraft_API + + + /** + * This is another abstract object type that groups together a number of font related methods that are used by multiple other widget types. + * This doesn't have a direct correlation to a UI object. See FontInstance object information for details. + */ + interface FontInstance extends UIObject { + + /** + * Returns detailed information on a font object. + * @returns MultipleReturnValues: + * - **fontName**: Path to font file + * - **fontHeight**: Font height in pixels. Due to internal graphics engine workings, this will be ridiculously close to an integer number, + * but not quite ever fully. + * - **fontFlags**: See FontInstance:SetFont(). + * @tupleReturn + */ + GetFont(): [string, number, string]; + + /** + * Gets the text color of of a Font Instance. + * @return MultipleReturnValues: + * r: The red color + * g: The green color + * b: The blue color + * a?: the alpha (opacity) + * @tupleReturn + */ + GetTextColor(): [number, number, number, number?]; + + /** + * The function is used to set the font to use for displaying text. + * + * @param font path to the font file, relative to the WoW base directory. + * @param size size in points. + * @param flags any comma-delimited combination of "OUTLINE", "THICKOUTLINE" and "MONOCHROME". + */ + SetFont(font: string, size: number, flags?: FontInstanceFlags): void; + + /** + * Sets horizontal text justification + * + * @param align the new align + */ + SetJustifyH(align: HorizontalAlign): void; + + /** + * Sets vertical text justification + * + * @param align the new align + */ + SetJustifyV(align: VerticalAlign): void; + + /** + * Sets the default text color. + * + * @param r red color + * @param g green color + * @param b blue color + * @param a alpha (opacity) + */ + SetTextColor(r: number, g: number, b: number, a?: number): void; + } +## GetFont +This will return detailed information about the current font instanceof. + +### Parameters +None + +### Returns +**fontName** string - Path to font file +**fontHeight** number - Font height in pixels. Due to internal graphics engine workings, this will be ridiculously close to an integer number, but not quite ever fully +**fontFlags** atring - string - Any comma-delimited combination of OUTLINE, THICK and MONOCHROME; otherwise must be at least an empty string (except for FontString objects). + +### Example Usage: +Get the font information for the current font instance. +```typescript +const myfont = CreateFont("Fonts\\FRIZQT__.TTF", 12, "OUTLINE"); + +const [fontName, height, flags] = myfont.GetFont(); +const text = myFrame.CreateFontString(myId, "OVERLAY", myfont); +text.SetText("Hello, World!"); + +``` +## SetFont +This will change the font details on an existing font instance. + +### Parameters
+**fontName** string - Path to font file +**fontHeight** number - Font height in pixels. Due to internal graphics engine workings, this will be ridiculously close to an integer number, but not quite ever fully +**fontFlags** atring - string - Any comma-delimited combination of OUTLINE, THICK and MONOCHROME; otherwise must be at least an empty string (except for FontString objects). + +### Example Usage: +```typescript +const myfont = CreateFont("Fonts\\FRIZQT__.TTF", 12, "OUTLINE"); +myFont.SetFont("Fonts\\Arial.TTF", 10, "OUTLINE"); + +const [fontName, height, flags] = myfont.GetFont(); +const text = myFrame.CreateFontString(myId, "OVERLAY", myfont); +text.SetText("I am Arial now!"); +```