building a team picker for cs nights
3m read
on this page
sorteador dos crias started as a five-name randomiser and grew a feature every time the group found a new thing to argue about. these are the decisions that held up.
##no sdk, no installer
every windows install has .net framework 4 and its compiler at
%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\csc.exe. that is enough to
build a wpf app, so the build is one batch file:
set FW=%WINDIR%\Microsoft.NET\Framework64\v4.0.30319
"%FW%\csc.exe" /nologo /codepage:65001 /optimize+ /target:winexe ^
/out:SorteadorDosCrias.exe /win32icon:icone.ico /win32manifest:app.manifest ^
/r:"%FW%\WPF\PresentationFramework.dll" /r:"%FW%\WPF\PresentationCore.dll" ^
/r:"%FW%\WPF\WindowsBase.dll" /r:"%FW%\System.Xaml.dll" ^
/resource:MainWindow.xaml,MainWindow.xaml ^
Program.csthe catch is that this compiler stops at c# 5: no string interpolation, no
?., no out var. the window is xaml embedded as a resource and loaded with
XamlReader.Load, so there is no x:Class and no generated code-behind;
controls are found by name and wired by hand.
/codepage:65001 makes the compiler read the source as utf-8. the discord
export keeps its emoji in string literals, and the system code page would not
survive them.
##looking like windows 11
wpf's default controls look like 2010. the fix was a handful of control templates (rounded buttons, a segmented selector, a text box with an accent underline on focus) and two dwm calls on the window handle:
int dark = 1;
DwmSetWindowAttribute(hwnd, 20, ref dark, 4); // dark title bar
int mica = 2;
DwmSetWindowAttribute(hwnd, 38, ref mica, 4); // mica backdropmica only shows through if the window background is transparent, the
HwndSource composition target is transparent, and the frame is extended into
the whole client area with DwmExtendFrameIntoClientArea. below build 22000
the app skips the backdrop and keeps a solid background.
##fair draws under rules
the shuffle is fisher–yates over RandomNumberGenerator, which is more than a
team picker needs and costs nothing.
the rules made it interesting. "felps and vitao never on the same team" and "whoever sat out last plays next" both constrain the result, and the easy fixes bias it: swapping players after the fact favours some splits over others.
priority is handled by construction. the starred players fill slots first, the rest of the slots come from a shuffle of everyone else, and only then are the chosen players shuffled into teams. the never-together pairs are handled by rejection: shuffle, check every pair, try again. every valid split is equally likely, and with eleven players a valid one turns up in a few tries. after 5000 misses the app says the rules cannot all hold instead of looping.
the priority only reads the last registered match. if it followed every draw, rerolling a split you did not like would quietly change who was guaranteed a slot.
##the console command
the map step ends with a button that copies:
game_type 0; game_mode 1; map de_infernogame_type 0 with game_mode 1 is competitive. map names get de_ unless
they are hostage maps like office and italy, which get cs_.
##smartscreen
friends who downloaded the exe got "windows protected your pc". defender found nothing; this is smartscreen saying it has never seen the file, and it shows for any unsigned exe that arrives from the internet.
adding version info, a manifest that asks for no elevation and an icon makes the file look like a normal program, but it does not remove the prompt. a code-signing certificate does, eventually: smartscreen still wants reputation, and since 2024 not even an ev certificate skips that. for eleven people the answer is more info → run anyway once per machine, or sending the folder and letting each person run the batch file, since an exe compiled locally carries no mark of the web.