Add project files.
This commit is contained in:
parent
ad28a7bcfa
commit
9136ea2284
4 changed files with 541 additions and 0 deletions
3
QuizTools.slnx
Normal file
3
QuizTools.slnx
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<Solution>
|
||||
<Project Path="QuizTools/QuizTools.csproj" />
|
||||
</Solution>
|
||||
382
QuizTools/Program.cs
Normal file
382
QuizTools/Program.cs
Normal file
|
|
@ -0,0 +1,382 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Dapper;
|
||||
using Microsoft.Data.SqlClient;
|
||||
using QuestPDF.Fluent;
|
||||
using QuestPDF.Helpers;
|
||||
using QuestPDF.Infrastructure;
|
||||
|
||||
namespace QuizTools
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
const int MaxQuestionImageHeight = 60;
|
||||
const int MaxAnswerImageHeight = 40;
|
||||
static void Main(string[] args)
|
||||
{
|
||||
// 1. License Configuration
|
||||
QuestPDF.Settings.License = LicenseType.Community;
|
||||
|
||||
string connectionString = "Server=localhost;Database=idpbw;Trusted_Connection=True;TrustServerCertificate=True;";
|
||||
|
||||
Console.WriteLine("Fetching data from SQL Server...");
|
||||
var modules = FetchQuizData(connectionString);
|
||||
|
||||
Console.WriteLine("Generating PDF Booklet...");
|
||||
GeneratePdfBooklet(modules, "Quiz_Review_Booklet.pdf");
|
||||
|
||||
Console.WriteLine("PDF generated successfully!");
|
||||
}
|
||||
|
||||
// --- Data Models ---
|
||||
public class ModuleModel
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string NameNL { get; set; } = string.Empty;
|
||||
public string NameFR { get; set; } = string.Empty;
|
||||
public string NameEN { get; set; } = string.Empty;
|
||||
public List<QuestionModel> Questions { get; set; } = new();
|
||||
}
|
||||
|
||||
public class QuestionModel
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public byte[]? Image { get; set; }
|
||||
public Dictionary<string, string> Text { get; set; } = new();
|
||||
public List<AnswerModel> Answers { get; set; } = new();
|
||||
}
|
||||
|
||||
public class AnswerModel
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public bool IsCorrect { get; set; }
|
||||
public byte[]? Image { get; set; }
|
||||
public Dictionary<string, string> Text { get; set; } = new();
|
||||
}
|
||||
|
||||
// --- Database Fetching ---
|
||||
static List<ModuleModel> FetchQuizData(string connStr)
|
||||
{
|
||||
using IDbConnection db = new SqlConnection(connStr);
|
||||
string query = @"
|
||||
SELECT m.moduleId AS ModuleId, m.naamNL AS ModuleNameNL,m.naamFR AS ModuleNameFR, m.naamEN AS ModuleNameEN, q.vraagId AS QuestionId, q.NL AS QTextNL, q.FR AS QTextFR, q.EN AS QTextEN, q_img.Image AS QImage, a.antwId AS AnswerId, a.NL AS ATextNL, a.FR AS ATextFR, a.EN AS ATextEN, a.correct AS IsCorrect, a_img.Image AS AImage
|
||||
FROM dbo.modules m
|
||||
JOIN quiz.vragen q ON m.moduleId=q.moduleId
|
||||
LEFT JOIN dbo.QuizImages q_img ON q.QuizImageId=q_img.QuizImageId
|
||||
JOIN quiz.antwoorden a ON q.vraagId=a.vraagId
|
||||
LEFT JOIN dbo.QuizImages a_img ON a.QuizImageId=a_img.QuizImageId
|
||||
WHERE q.active=1 AND q.deleted=0
|
||||
ORDER BY m.moduleId, q.vraagId, a.antwId;
|
||||
";
|
||||
|
||||
var rows = db.Query(query);
|
||||
var modulesDict = new Dictionary<int, ModuleModel>();
|
||||
|
||||
foreach (var row in rows)
|
||||
{
|
||||
int modId = row.ModuleId;
|
||||
if (!modulesDict.TryGetValue(modId, out var module))
|
||||
{
|
||||
module = new ModuleModel
|
||||
{
|
||||
Id = modId,
|
||||
NameNL = row.ModuleNameNL ?? string.Empty,
|
||||
NameFR = row.ModuleNameFR ?? string.Empty,
|
||||
NameEN = row.ModuleNameEN ?? string.Empty
|
||||
};
|
||||
modulesDict[modId] = module;
|
||||
}
|
||||
|
||||
int qId = row.QuestionId;
|
||||
var question = module.Questions.FirstOrDefault(q => q.Id == qId);
|
||||
if (question == null)
|
||||
{
|
||||
byte[]? qImage = row.QImage is DBNull ? null : (byte[]?)row.QImage;
|
||||
if (qImage != null && qImage.Length <100) qImage = null;
|
||||
question = new QuestionModel { Id = qId, Image = qImage };
|
||||
module.Questions.Add(question);
|
||||
}
|
||||
question.Text["nl"] = row.QTextNL;
|
||||
question.Text["fr"] = row.QTextFR;
|
||||
question.Text["en"] = row.QTextEN;
|
||||
|
||||
int aId = row.AnswerId;
|
||||
var answer = question.Answers.FirstOrDefault(a => a.Id == aId);
|
||||
if (answer == null)
|
||||
{
|
||||
byte[]? aImage = row.AImage is DBNull ? null : (byte[]?)row.AImage;
|
||||
if (aImage != null && aImage.Length < 100) aImage = null;
|
||||
answer = new AnswerModel { Id = aId, IsCorrect = row.IsCorrect, Image = aImage };
|
||||
question.Answers.Add(answer);
|
||||
}
|
||||
answer.Text["nl"] = row.ATextNL;
|
||||
answer.Text["fr"] = row.ATextFR;
|
||||
answer.Text["en"] = row.ATextEN;
|
||||
}
|
||||
|
||||
return modulesDict.Values.ToList();
|
||||
}
|
||||
|
||||
// --- PDF Generation Logic ---
|
||||
static void GeneratePdfBooklet(List<ModuleModel> modules, string outputPath)
|
||||
{
|
||||
Document.Create(container =>
|
||||
{
|
||||
//container.WithSettings(settings =>
|
||||
//{
|
||||
// settings.PdfA = false; // Set to true if you need PDF/A compliance
|
||||
//});
|
||||
|
||||
container.Page(page =>
|
||||
{
|
||||
page.Size(PageSizes.A4);
|
||||
page.Margin(15, Unit.Millimetre);
|
||||
page.DefaultTextStyle(x => x.FontFamily("Segoe UI").FontSize(9).FontColor("#1E293B"));
|
||||
|
||||
page.Header().Element(ComposeDocumentHeader);
|
||||
|
||||
page.Content().PaddingVertical(10).Column(column =>
|
||||
{
|
||||
bool isFirstModule = true;
|
||||
|
||||
foreach (var module in modules)
|
||||
{
|
||||
// Avoid inserting a blank page break before the very first cover page
|
||||
if (!isFirstModule)
|
||||
{
|
||||
column.Item().PageBreak();
|
||||
}
|
||||
isFirstModule = false;
|
||||
|
||||
// 1. Render Full-Page Module Cover
|
||||
column.Item().Element(c => ComposeModuleTitlePage(c, module));
|
||||
|
||||
// 2. Start Questions on a Fresh Page Right After Title
|
||||
column.Item().PageBreak();
|
||||
|
||||
// 3. Render Question Cards for this Module
|
||||
column.Item().Column(qCol =>
|
||||
{
|
||||
qCol.Spacing(15);
|
||||
foreach (var question in module.Questions)
|
||||
{
|
||||
qCol.Item().Element(c => ComposeQuestionCard(c, question));
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
page.Footer().Element(ComposeDocumentFooter);
|
||||
});
|
||||
}).WithMetadata(new DocumentMetadata
|
||||
{
|
||||
Title = "Quiz Review Booklet",
|
||||
Author = "LSW-Tech Luc Vandenbroucke",
|
||||
Subject = "Multilingual Quiz Questions and Answers (NL / FR / EN)",
|
||||
Keywords = "Quiz, HPH",
|
||||
Creator = "QuizTools Application"
|
||||
}).GeneratePdf(outputPath);
|
||||
}
|
||||
static void ComposeModuleTitlePage(IContainer container, ModuleModel module)
|
||||
{
|
||||
container.AlignCenter().AlignMiddle().Column(col =>
|
||||
{
|
||||
// Badge Header
|
||||
col.Item().AlignCenter().Background("#1E293B").PaddingHorizontal(12).PaddingVertical(4)
|
||||
.CornerRadius(4).Text($"MODULE {module.Id}").Bold().FontSize(12).FontColor("#FFFFFF");
|
||||
|
||||
// Module Names Stacked
|
||||
col.Item().PaddingTop(20).AlignCenter().Text(module.NameNL)
|
||||
.Bold().FontSize(22).FontColor("#0F172A");
|
||||
|
||||
col.Item().PaddingTop(6).AlignCenter().Text(module.NameFR)
|
||||
.SemiBold().FontSize(18).FontColor("#3B82F6");
|
||||
|
||||
col.Item().PaddingTop(6).AlignCenter().Text(module.NameEN)
|
||||
.Medium().FontSize(16).FontColor("#10B981");
|
||||
|
||||
// Decorative Accent Bar
|
||||
col.Item().PaddingTop(25).Width(100).Height(3).Background("#CBD5E1");
|
||||
|
||||
// Question Counter
|
||||
col.Item().PaddingTop(15).AlignCenter().Text($"{module.Questions.Count} Questions")
|
||||
.FontSize(11).FontColor("#64748B");
|
||||
});
|
||||
}
|
||||
|
||||
// --- Header Component ---
|
||||
static void ComposeDocumentHeader(IContainer container)
|
||||
{
|
||||
container.BorderBottom(1).BorderColor("#E2E8F0").PaddingBottom(5).Row(row =>
|
||||
{
|
||||
row.RelativeItem().Text("Quiz Questions and Answers").Bold().FontSize(10).FontColor("#1E293B");
|
||||
row.AutoItem().Text("23/08/2026").FontSize(10).FontColor("#64748B");
|
||||
});
|
||||
}
|
||||
|
||||
// --- First-Page Title Banner Component ---
|
||||
static void ComposeTitleBanner(IContainer container)
|
||||
{
|
||||
container.Background("#F8FAFC").Border(1).BorderColor("#CBD5E1").CornerRadius(4).Padding(12).Row(row =>
|
||||
{
|
||||
row.RelativeItem().Column(col =>
|
||||
{
|
||||
col.Item().Text("Quiz Questions and Answers").Bold().FontSize(18).FontColor("#0F172A");
|
||||
col.Item().PaddingTop(2).Text("Multilingual Module Review Export (NL / FR / EN)").FontSize(10).FontColor("#64748B");
|
||||
});
|
||||
row.AutoItem().AlignBottom().Text("Date: 23/08/2026").FontSize(10).FontColor("#64748B");
|
||||
});
|
||||
}
|
||||
|
||||
// --- Footer Component ---
|
||||
//static void ComposeDocumentFooter(IContainer container)
|
||||
//{
|
||||
// container.BorderTop(1).BorderColor("#E2E8F0").PaddingTop(5).Row(row =>
|
||||
// {
|
||||
// // Left side: Creator info & date
|
||||
// row.RelativeItem().Text(x =>
|
||||
// {
|
||||
// x.Span("Created by ").FontColor("#64748B");
|
||||
// x.Span("Luc Vandenbroucke").Bold().FontColor("#1E293B");
|
||||
// x.Span(" — 23.08.2026").FontColor("#64748B");
|
||||
// });
|
||||
|
||||
// // Right side: Dynamic Page Numbering
|
||||
// row.AutoItem().Text(x =>
|
||||
// {
|
||||
// x.Span("Page ").FontColor("#64748B");
|
||||
// x.CurrentPageNumber().FontColor("#1E293B").Bold();
|
||||
// x.Span(" of ").FontColor("#64748B");
|
||||
// x.TotalPages().FontColor("#1E293B").Bold();
|
||||
// });
|
||||
// });
|
||||
//}
|
||||
|
||||
static string GetSvgContent(string filePath)
|
||||
{
|
||||
if (File.Exists(filePath))
|
||||
{
|
||||
return File.ReadAllText(filePath);
|
||||
}
|
||||
|
||||
// Fallback minimal SVG dot if file is missing
|
||||
return @"<svg height='20' width='20'><circle cx='10' cy='10' r='8' fill='#1E293B'/></svg>";
|
||||
}
|
||||
|
||||
static void ComposeDocumentFooter(IContainer container)
|
||||
{
|
||||
// Read your SVG string from file or a string variable
|
||||
string mySvg = GetSvgContent("images\\lswtech300-95.svg");
|
||||
|
||||
container.BorderTop(1).BorderColor("#E2E8F0").PaddingTop(5).Row(row =>
|
||||
{
|
||||
// Left side: Render SVG image (constrained in height)
|
||||
row.RelativeItem().Row(leftRow =>
|
||||
{
|
||||
leftRow.AutoItem()
|
||||
.MaxHeight(16) // Keeps the SVG small and aligned with footer text
|
||||
.Svg(mySvg);
|
||||
|
||||
leftRow.AutoItem()
|
||||
.PaddingLeft(6)
|
||||
.AlignMiddle()
|
||||
.Text("— 23.08.2026")
|
||||
.FontSize(8)
|
||||
.FontColor("#64748B");
|
||||
});
|
||||
|
||||
// Right side: Page Numbering
|
||||
row.AutoItem().AlignMiddle().Text(x =>
|
||||
{
|
||||
x.Span("Page ").FontColor("#64748B");
|
||||
x.CurrentPageNumber().FontColor("#1E293B").Bold();
|
||||
x.Span(" of ").FontColor("#64748B");
|
||||
x.TotalPages().FontColor("#1E293B").Bold();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
static void ComposeModuleHeader(IContainer container, string title)
|
||||
{
|
||||
container.BorderBottom(2).BorderColor("#1E293B").PaddingBottom(5).Text(title)
|
||||
.FontSize(16).Bold().FontColor("#1E293B");
|
||||
}
|
||||
|
||||
static void ComposeQuestionCard(IContainer container, QuestionModel q)
|
||||
{
|
||||
// NO .ShowEntire() on the root container so multi-page questions can render
|
||||
container.ShowEntire().Border(1).BorderColor("#CBD5E1").CornerRadius(4).Column(column =>
|
||||
{
|
||||
// 1. Keep the card header together with the first text block if possible
|
||||
column.Item().ShowEntire().Background("#1E293B").Padding(6)
|
||||
.Text($"Question #{q.Id}").Bold().FontColor("#FFFFFF");
|
||||
|
||||
column.Item().Padding(10).Column(body =>
|
||||
{
|
||||
// Question Image
|
||||
if (q.Image != null && q.Image.Length > 0)
|
||||
{
|
||||
body.Item().PaddingVertical(6).AlignCenter().MaxHeight(MaxQuestionImageHeight ).Image(q.Image);
|
||||
}
|
||||
|
||||
// Language Text Blocks
|
||||
ComposeLangBlock(body, "NL", q.Text.GetValueOrDefault("nl"), "#F97316");
|
||||
ComposeLangBlock(body, "FR", q.Text.GetValueOrDefault("fr"), "#3B82F6");
|
||||
ComposeLangBlock(body, "EN", q.Text.GetValueOrDefault("en"), "#10B981");
|
||||
|
||||
// Answers Section
|
||||
body.Item().PaddingTop(8).Text("ANSWERS").Bold().FontSize(8).FontColor("#64748B");
|
||||
|
||||
foreach (var ans in q.Answers)
|
||||
{
|
||||
// Each individual answer option stays intact on one page
|
||||
body.Item().PaddingTop(5).Element(c => ComposeAnswerCard(c, ans));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
static void ComposeAnswerCard(IContainer container, AnswerModel a)
|
||||
{
|
||||
string borderColor = a.IsCorrect ? "#86EFAC" : "#E2E8F0";
|
||||
string bgColor = a.IsCorrect ? "#F0FDF4" : "#FFFFFF";
|
||||
|
||||
// .ShowEntire() here prevents individual answer choices from splitting mid-text
|
||||
container.ShowEntire().Border(1).BorderColor(borderColor).Background(bgColor).CornerRadius(4).Padding(6).Column(col =>
|
||||
{
|
||||
col.Item().Row(row =>
|
||||
{
|
||||
row.RelativeItem().Text($"Option {a.Id}").Bold();
|
||||
if (a.IsCorrect)
|
||||
{
|
||||
row.AutoItem().Background("#16A34A").PaddingHorizontal(4).PaddingVertical(1)
|
||||
.CornerRadius(2).Text("CORRECT").FontSize(7).Bold().FontColor("#FFFFFF");
|
||||
}
|
||||
});
|
||||
|
||||
if (a.Image != null && a.Image.Length > 0)
|
||||
{
|
||||
col.Item().PaddingVertical(4).AlignCenter().MaxHeight(MaxAnswerImageHeight).Image(a.Image);
|
||||
}
|
||||
|
||||
ComposeLangBlock(col, "NL", a.Text.GetValueOrDefault("nl"), "#F97316");
|
||||
ComposeLangBlock(col, "FR", a.Text.GetValueOrDefault("fr"), "#3B82F6");
|
||||
ComposeLangBlock(col, "EN", a.Text.GetValueOrDefault("en"), "#10B981");
|
||||
});
|
||||
}
|
||||
|
||||
static void ComposeLangBlock(ColumnDescriptor column, string tag, string? text, string accentColor)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(text)) return;
|
||||
|
||||
column.Item().PaddingTop(3).BorderLeft(3).BorderColor(accentColor).Background("#F8FAFC").Padding(4).Row(row =>
|
||||
{
|
||||
row.AutoItem().PaddingRight(5).Text(tag).Bold().FontSize(8).FontColor("#64748B");
|
||||
row.RelativeItem().Text(text);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
26
QuizTools/QuizTools.csproj
Normal file
26
QuizTools/QuizTools.csproj
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="images\lswtech300-95.svg" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="images\lswtech300-95.svg">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Dapper" Version="2.1.79" />
|
||||
<PackageReference Include="Microsoft.Data.SqlClient" Version="7.0.2" />
|
||||
<PackageReference Include="QuestPDF" Version="2026.7.3" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
130
QuizTools/images/lswtech300-95.svg
Normal file
130
QuizTools/images/lswtech300-95.svg
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="300"
|
||||
height="95"
|
||||
version="1.1"
|
||||
viewBox="0 0 300 95"
|
||||
id="svg8"
|
||||
sodipodi:docname="lswtech300-95.svg"
|
||||
inkscape:version="1.4.4 (dcaf3e7, 2026-05-05)"
|
||||
inkscape:export-filename="lswtech300-95.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<defs
|
||||
id="defs8" />
|
||||
<sodipodi:namedview
|
||||
id="namedview8"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:zoom="3.6439569"
|
||||
inkscape:cx="136.3902"
|
||||
inkscape:cy="36.087144"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="991"
|
||||
inkscape:window-x="-9"
|
||||
inkscape:window-y="-9"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg8" />
|
||||
<title
|
||||
id="title1">LSW-Tech Logo</title>
|
||||
<g
|
||||
transform="matrix(0.85855447,0,0,0.8240687,22.973632,-50.235044)"
|
||||
id="g8">
|
||||
<g
|
||||
transform="translate(43.648,35.231)"
|
||||
id="g7">
|
||||
<g
|
||||
fill="#08fcfc"
|
||||
fill-opacity="0.38824"
|
||||
id="g4">
|
||||
<ellipse
|
||||
cx="55.393002"
|
||||
cy="68.566002"
|
||||
rx="3.3863001"
|
||||
ry="3.3218"
|
||||
id="ellipse1" />
|
||||
<ellipse
|
||||
cx="22.82"
|
||||
cy="75.403"
|
||||
rx="3.3863001"
|
||||
ry="3.3218"
|
||||
id="ellipse2" />
|
||||
<ellipse
|
||||
cx="-1.1739"
|
||||
cy="96.558998"
|
||||
rx="3.3863001"
|
||||
ry="3.3218"
|
||||
id="ellipse3" />
|
||||
<ellipse
|
||||
cx="-11.946"
|
||||
cy="64.436996"
|
||||
rx="3.3863001"
|
||||
ry="3.3218"
|
||||
id="ellipse4" />
|
||||
</g>
|
||||
<path
|
||||
d="m -26.482,54.734 47.251,-26.818 46.703,27.548 -0.54731,57.832 -46.521,27 -46.703,-27.548 z"
|
||||
fill="none"
|
||||
stroke="#000000"
|
||||
stroke-width="2.065"
|
||||
id="path4" />
|
||||
<path
|
||||
d="M 88.465,99.752 V 75.67 h 5.0631 v 24.082 z m 15.644,0.25965 q -2.2394,0 -4.3166,-0.51929 -2.0447,-0.55175 -3.2456,-1.3631 l 1.6877,-3.635 q 1.2008,0.74648 2.8236,1.2333 1.6552,0.45438 3.2456,0.45438 1.7526,0 2.4666,-0.42193 0.74648,-0.42192 0.74648,-1.1684 0,-0.61666 -0.5842,-0.90876 -0.55175,-0.32455 -1.493,-0.48683 -0.94125,-0.16228 -2.0772,-0.32456 -1.1035,-0.16227 -2.2394,-0.42192 -1.1359,-0.2921 -2.0771,-0.84384 -0.94122,-0.55175 -1.5254,-1.493 -0.55174,-0.94121 -0.55174,-2.4342 0,-1.6552 0.94121,-2.921 0.97367,-1.2658 2.7912,-1.9798 1.8175,-0.74648 4.349,-0.74648 1.7851,0 3.635,0.38947 1.8499,0.38947 3.0833,1.136 l -1.6877,3.6026 q -1.2658,-0.74648 -2.564,-1.0061 -1.2658,-0.2921 -2.4666,-0.2921 -1.6877,0 -2.4666,0.45438 -0.77894,0.45438 -0.77894,1.1684 0,0.64912 0.55175,0.97367 0.5842,0.32456 1.5254,0.51929 0.94121,0.19474 2.0447,0.35701 1.136,0.12983 2.2719,0.42193 1.1359,0.2921 2.0447,0.84384 0.94121,0.51929 1.5254,1.4605 0.5842,0.90876 0.5842,2.4017 0,1.6228 -0.97367,2.8886 -0.97366,1.2333 -2.8236,1.9473 -1.8175,0.71403 -4.4464,0.71403 z M 119.136,99.752 112.8396,82.291 h 4.771 l 5.2254,15.027 h -2.2719 l 5.4525,-15.027 h 4.2841 l 5.2903,15.027 h -2.2719 l 5.3876,-15.027 h 4.4789 l -6.3288,17.461 h -4.9008 l -4.6412,-12.885 h 1.493 l -4.8034,12.885 z m 25.25,-7.1078 v -4.057 h 9.1849 v 4.057 z m 20.642,7.3674 q -3.0833,0 -4.8034,-1.5579 -1.7202,-1.5903 -1.7202,-4.7061 v -15.319 h 5.0631 v 15.254 q 0,1.1035 0.5842,1.7202 0.5842,0.5842 1.5903,0.5842 1.2008,0 2.0447,-0.64911 l 1.3631,3.5701 q -0.77894,0.55174 -1.8824,0.84384 -1.071,0.25965 -2.2394,0.25965 z m -9.2174,-13.826 v -3.8947 h 12.106 v 3.8947 z m 24.309,13.826 q -2.9859,0 -5.2578,-1.1684 -2.2394,-1.1684 -3.4728,-3.1806 -1.2333,-2.0447 -1.2333,-4.6412 0,-2.6289 1.2009,-4.6412 1.2333,-2.0447 3.3429,-3.1806 2.1096,-1.1684 4.771,-1.1684 2.564,0 4.6087,1.1035 2.0772,1.071 3.278,3.1157 1.2009,2.0122 1.2009,4.8359 0,0.2921 -0.0325,0.68156 -0.0325,0.35701 -0.0649,0.68157 h -14.183 v -2.9535 h 11.522 l -1.9473,0.8763 q 0,-1.3631 -0.55175,-2.3693 -0.55175,-1.0061 -1.5254,-1.5579 -0.97367,-0.5842 -2.2719,-0.5842 -1.2982,0 -2.3043,0.5842 -0.97367,0.55175 -1.5254,1.5903 -0.55174,1.0061 -0.55174,2.4017 v 0.77894 q 0,1.428 0.61666,2.5315 0.64911,1.071 1.785,1.6552 1.1684,0.55175 2.7263,0.55175 1.3956,0 2.4342,-0.42193 1.071,-0.42192 1.9473,-1.2658 l 2.6938,2.921 q -1.2008,1.3631 -3.0184,2.1096 -1.8175,0.71403 -4.1868,0.71403 z m 20.252,0 q -2.8236,0 -5.0306,-1.136 -2.207,-1.1684 -3.4728,-3.2131 -1.2333,-2.0447 -1.2333,-4.6412 0,-2.6289 1.2333,-4.6412 1.2658,-2.0447 3.4728,-3.1806 2.207,-1.1684 5.0306,-1.1684 2.7587,0 4.8034,1.1684 2.0447,1.136 3.0184,3.278 l -3.9271,2.1096 q -0.68156,-1.2333 -1.7201,-1.8175 -1.0061,-0.5842 -2.207,-0.5842 -1.2982,0 -2.3368,0.5842 -1.0386,0.5842 -1.6552,1.6552 -0.5842,1.071 -0.5842,2.5964 0,1.5254 0.5842,2.5964 0.61665,1.071 1.6552,1.6552 1.03855,0.5842 2.3368,0.5842 1.2008,0 2.207,-0.55175 1.0386,-0.5842 1.7201,-1.85 l 3.9271,2.1421 q -0.97367,2.1096 -3.0184,3.278 -2.0447,1.136 -4.8034,1.136 z m 10.613,-0.25965 v -24.082 h 5.0631 v 11.457 l -1.136,-1.4605 q 0.94121,-1.7526 2.6938,-2.6938 1.7526,-0.94122 3.992,-0.94122 2.0772,0 3.6999,0.84385 1.6552,0.81139 2.5964,2.5315 0.94121,1.6877 0.94121,4.349 v 9.9963 h -5.0631 v -9.2174 q 0,-2.1096 -0.94121,-3.1157 -0.90876,-1.0061 -2.5964,-1.0061 -1.2009,0 -2.1745,0.51929 -0.94121,0.48683 -1.493,1.5254 -0.51929,1.0386 -0.51929,2.6614 v 8.6332 z"
|
||||
stroke-width="0.26458"
|
||||
style="font-variant-ligatures:none"
|
||||
aria-label="lsw-tech"
|
||||
id="path5" />
|
||||
<path
|
||||
d="m 59.377,68.598 a 3.9511,3.9511 0 0 1 -3.9511,3.9511 3.9511,3.9511 0 0 1 -3.9511,-3.9511 3.9511,3.9511 0 0 1 3.9511,-3.9511 3.9511,3.9511 0 0 1 3.9511,3.9511 z m -32.508,6.9016 a 3.9511,3.9511 0 0 1 -3.9511,3.9511 3.9511,3.9511 0 0 1 -3.9511,-3.9511 3.9511,3.9511 0 0 1 3.9511,-3.9511 3.9511,3.9511 0 0 1 3.9511,3.9511 z m -19.286,33.863 a 3.9511,3.9511 0 0 1 -3.9511,3.9511 3.9511,3.9511 0 0 1 -3.9511,-3.9511 3.9511,3.9511 0 0 1 3.9511,-3.9511 3.9511,3.9511 0 0 1 3.9511,3.9511 z m 16.64,-29.634 6.4344,18.024 7.5466,-20.576 7.7401,20.382 8.4496,-24.704 m -47.213,33.55 12.189,-12.523 C 2.1557,83.0456 7.0287,85.69 0.5997,81.7556 l 16.899,-17.286 3.2661,6.8735"
|
||||
fill="none"
|
||||
stroke="#000000"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="1.7608"
|
||||
id="path6" />
|
||||
<path
|
||||
d="m -7.9622,64.47 a 3.9511,3.9511 0 0 1 -3.9511,3.9511 3.9511,3.9511 0 0 1 -3.9511,-3.9511 3.9511,3.9511 0 0 1 3.9511,-3.9511 3.9511,3.9511 0 0 1 3.9511,3.9511 z m 10.772,32.25 a 3.9511,3.9511 0 0 1 -3.9511,3.9511 3.9511,3.9511 0 0 1 -3.9511,-3.9511 3.9511,3.9511 0 0 1 3.9511,-3.9511 3.9511,3.9511 0 0 1 3.9511,3.9511 z m -14.852,-27.885 v 27.95 h 6.194"
|
||||
fill="none"
|
||||
stroke="#000000"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="1.7608"
|
||||
id="path7" />
|
||||
<ellipse
|
||||
cx="3.6636"
|
||||
cy="109.33"
|
||||
rx="3.3863001"
|
||||
ry="3.3218"
|
||||
fill="#08fcfc"
|
||||
fill-opacity="0.38824"
|
||||
id="ellipse7" />
|
||||
</g>
|
||||
</g>
|
||||
<metadata
|
||||
id="metadata8">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:title>LSW-Tech Logo</dc:title>
|
||||
<dc:date>2026-06-12</dc:date>
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>Luc Vandenbroucke</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 7.7 KiB |
Loading…
Add table
Reference in a new issue