Sebastian Walz 860d31cee1
Tohu vaBohu
2023-04-21 00:22:52 +02:00

202 lines
7.5 KiB
Nix

{ core, document, helpers, symbols, styles, toTex, ... }:
{ maxStars ? 5, ... }:
let
inherit(core) debug indentation list number set string type;
inherit(document) Multilingual;
inherit(helpers) formatSection;
inherit(symbols.forkAwesome) star star-half-o star-o;
toTex' = body: string.concatWith " " (toTex body);
languageLevels
= {
"native"
= {
description
= {
deu = "Muttersprache";
eng = "Native Language";
};
level = Multilingual { deu = "nativ"; eng = "native"; };
stars = 1.0;
};
"C2"
= {
description
= {
deu = "Kompetente Sprachverwendung";
eng = "Proficient User";
};
level = "C2";
stars = 7 / 8.;
};
"C1"
= {
description
= {
deu = "Kompetente Sprachverwendung";
eng = "Proficient User";
};
level = "C1";
stars = 6 / 8.;
};
"B2"
= {
description
= {
deu = "Selbstständige Sprachverwendung";
eng = "Independent User";
};
level = "B2";
stars = 5 / 8.;
};
"B1"
= {
description
= {
deu = "Selbstständige Sprachverwendung";
eng = "Independent User";
};
level = "B1";
stars = 4 / 8.;
};
"A2"
= {
description
= {
deu = "Elementare Sprachverwendung";
eng = "Basic User";
};
level = "A2";
stars = 3 / 8.;
};
"A1"
= {
description
= {
deu = "Elementare Sprachverwendung";
eng = "Basic User";
};
level = "A1";
stars = 2 / 8.;
};
"latinum"
= {
description
= {
deu = "Latinum";
eng = "Latinum";
};
level = null;
stars = 1 / 8.;
};
};
languageNames
= {
ces = { deu = "Tschechisch"; eng = "Czech"; };
deu = { deu = "Deutsch"; eng = "German"; };
eng = { deu = "Englisch"; eng = "English"; };
epo = { deu = "Esperanto"; eng = "Esperanto"; };
heb = { deu = "Ivrit"; eng = "Ivrit"; };
lat = { deu = "Latein"; eng = "Latin"; };
};
rateHalfStars
= value:
maximum:
let
full = number.floor (value * maximum);
empty = number.floor ((1 - value) * maximum);
half = maximum - full - empty;
in
(list.generate (_: star) full)
++ (list.ifOrEmpty (half != 0) star-half-o)
++ (list.generate (_: star-o) empty);
formatLanguage
= name:
{ description, level, stars, ... }:
let
name' = styles.skillType (toTex' (Multilingual name));
level' = if level != null then styles.skillSet (toTex' level) else "";
description' = styles.description (toTex' (Multilingual description));
stars'
= if stars != null
then
string.concat (rateHalfStars stars maxStars)
else
"";
in
"${name'} & ${description'} & ${level'} & ${styles.entryLocation stars'} \\\\%";
in
languages:
let
emptyLevel
= {
description = "";
level = "";
stars = 0;
};
languages'
= set.mapToList
(
language:
level:
{
name = languageNames.${language} or language;
level
= type.matchPrimitiveOrPanic level
{
null = emptyLevel;
int
= debug.panic "languages'"
{
text = "Level of type integer must be between 0 and `maxStars` (${string maxStars}) inclusive, got:";
data = level;
when = level < 0 || level > maxStars;
}
( emptyLevel // { stars = 1.0 * level / maxStars; });
float
= debug.panic "languages'"
{
text = "Level of type float must be between 0.0 and 1.0 inclusive, got:";
data = level;
when = level < 0.0 || level > 1.0;
}
( emptyLevel // { stars = level; });
set = emptyLevel // level;
string = languageLevels.${level};
};
}
)
languages;
compare = foo: bar: foo.level.stars > bar.level.stars;
in
formatSection
(
Multilingual
{
deu = "Sprachen";
eng = "Languages";
}
)
(
[
"\\vspace{-1em}%"
"\\begin{center}%" indentation.more
"\\setlength{\\tabcolsep}{1ex}%"
"\\setlength{\\extrarowheight}{0pt}%"
"\\begin{tabularx}{\\textwidth}{rXrl}%" indentation.more
]
++ (
list.map
({ name, level }: formatLanguage name level)
(list.sort compare languages')
)
++ [
indentation.less "\\end{tabularx}%"
indentation.less "\\end{center}%"
]
)