Added a SWOT analysis assistant (#1122)

Co-authored-by: hart_s3 <sabrina.hartmann@dlr.de>
This commit is contained in:
Thorsten Sommerandhart_s3 authored and GitHub committed 2026-10-28 08:51:30 +01:00
1 parent 6cb20fd75a
commit 060a2a5734
87 files changed
+4601 -45

No files matched your search

@@ -0,0 +1,90 @@
using System.Text;
namespace AIStudio.Assistants.SWOTAnalysis;
/// <summary>
/// Writes a SWOT analysis as Markdown, the canonical text which providers, copying, exporting, and a
/// chat get.
/// </summary>
/// <remarks>
/// The order is the order of the result view: the matrix, the overall assessment, and the actions
/// first, which is what a reader needs for a decision; then the details of each category, and last
/// what the moderator changed.
/// </remarks>
internal static class SwotAnalysisMarkdownFormatter
{
public static string Format(SwotAnalysisResult result)
{
var markdown = new StringBuilder();
AppendHeading(markdown, result.MatrixHeading);
markdown.AppendLine($"| | {EscapeTableCell(result.PositiveLabel)} | {EscapeTableCell(result.NegativeLabel)} |");
markdown.AppendLine("|---|---|---|");
markdown.AppendLine($"| **{EscapeTableCell(result.InternalLabel)}** | {FormatCategoryCell(result.Strengths)} | {FormatCategoryCell(result.Weaknesses)} |");
markdown.AppendLine($"| **{EscapeTableCell(result.ExternalLabel)}** | {FormatCategoryCell(result.Opportunities)} | {FormatCategoryCell(result.Threats)} |");
markdown.AppendLine();
AppendHeading(markdown, result.OverallAssessment.Label);
foreach (var paragraph in result.OverallAssessment.Paragraphs)
{
markdown.AppendLine(Markdown.EscapeInlineText(paragraph));
markdown.AppendLine();
}
AppendHeading(markdown, result.PrioritizedActions.Label);
if (result.PrioritizedActions.Items.Count == 0)
markdown.AppendLine(Markdown.EscapeInlineText(result.PrioritizedActions.EmptyMessage));
else
for (var index = 0; index < result.PrioritizedActions.Items.Count; index++)
{
var action = result.PrioritizedActions.Items[index];
var factors = string.Join("; ", action.AddressedFactors.Select(Markdown.EscapeInlineText));
markdown.AppendLine($"{index + 1}. **{Markdown.EscapeInlineText(action.Action)}** — {Markdown.EscapeInlineText(action.Rationale)} ");
markdown.AppendLine($" *{factors}*");
}
markdown.AppendLine();
foreach (var category in result.Categories)
{
AppendHeading(markdown, category.Label);
if (category.Findings.Count == 0)
markdown.AppendLine(Markdown.EscapeInlineText(category.EmptyMessage));
else
foreach (var finding in category.Findings)
markdown.AppendLine($"- **{Markdown.EscapeInlineText(finding.Summary)}** — {Markdown.EscapeInlineText(finding.Explanation)}");
markdown.AppendLine();
}
AppendHeading(markdown, result.ModerationNotes.Label);
if (result.ModerationNotes.Items.Count == 0)
markdown.AppendLine(Markdown.EscapeInlineText(result.ModerationNotes.EmptyMessage));
else
foreach (var note in result.ModerationNotes.Items)
markdown.AppendLine($"- **{Markdown.EscapeInlineText(note.Change)}** — {Markdown.EscapeInlineText(note.Reason)}");
return markdown.ToString().TrimEnd();
}
private static void AppendHeading(StringBuilder markdown, string heading)
{
markdown.Append("## ");
markdown.AppendLine(Markdown.EscapeInlineText(heading));
}
private static string FormatCategoryCell(SwotCategory category)
{
var content = category.Findings.Count == 0
? EscapeTableCell(category.EmptyMessage)
: string.Join("; ", category.Findings.Select(finding => EscapeTableCell(finding.Summary)));
return $"**{EscapeTableCell(category.Label)}:** {content}";
}
private static string EscapeTableCell(string value) => value
.Replace("\\", "\\\\", StringComparison.Ordinal)
.Replace("|", "\\|", StringComparison.Ordinal)
.Replace('\r', ' ')
.Replace('\n', ' ')
.Trim();
}