From 0c85e000b401c1bab36d07b82c4a0b727562c42a Mon Sep 17 00:00:00 2001 From: Serghei Cebotari Date: Wed, 20 Sep 2023 08:18:22 +0300 Subject: [PATCH] Initial commit --- .gitignore | 477 ++++++++++++++++++ RhSolutions.ML.Builder/.gitignore | 477 ++++++++++++++++++ RhSolutions.ML.Builder/.vscode/launch.json | 26 + RhSolutions.ML.Builder/.vscode/tasks.json | 41 ++ RhSolutions.ML.Builder/Data/train.tsv | 351 +++++++++++++ RhSolutions.ML.Builder/Models/model.zip | Bin 0 -> 47211 bytes RhSolutions.ML.Builder/Product.cs | 16 + RhSolutions.ML.Builder/Program.cs | 42 ++ .../RhSolutions.ML.Builder.csproj | 18 + .../RhSolutions.ML.Tests.csproj | 25 + RhSolutions.ML.Tests/Tests.cs | 59 +++ RhSolutions.ML.Tests/Usings.cs | 2 + RhSolutions.ML.sln | 31 ++ 13 files changed, 1565 insertions(+) create mode 100644 .gitignore create mode 100644 RhSolutions.ML.Builder/.gitignore create mode 100644 RhSolutions.ML.Builder/.vscode/launch.json create mode 100644 RhSolutions.ML.Builder/.vscode/tasks.json create mode 100644 RhSolutions.ML.Builder/Data/train.tsv create mode 100644 RhSolutions.ML.Builder/Models/model.zip create mode 100644 RhSolutions.ML.Builder/Product.cs create mode 100644 RhSolutions.ML.Builder/Program.cs create mode 100644 RhSolutions.ML.Builder/RhSolutions.ML.Builder.csproj create mode 100644 RhSolutions.ML.Tests/RhSolutions.ML.Tests.csproj create mode 100644 RhSolutions.ML.Tests/Tests.cs create mode 100644 RhSolutions.ML.Tests/Usings.cs create mode 100644 RhSolutions.ML.sln diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..154e127 --- /dev/null +++ b/.gitignore @@ -0,0 +1,477 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET +project.lock.json +project.fragment.lock.json +artifacts/ + +# Tye +.tye/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml + +## +## Visual studio for Mac +## + + +# globs +Makefile.in +*.userprefs +*.usertasks +config.make +config.status +aclocal.m4 +install-sh +autom4te.cache/ +*.tar.gz +tarballs/ +test-results/ + +# Mac bundle stuff +*.dmg +*.app + +# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk diff --git a/RhSolutions.ML.Builder/.gitignore b/RhSolutions.ML.Builder/.gitignore new file mode 100644 index 0000000..154e127 --- /dev/null +++ b/RhSolutions.ML.Builder/.gitignore @@ -0,0 +1,477 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET +project.lock.json +project.fragment.lock.json +artifacts/ + +# Tye +.tye/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml + +## +## Visual studio for Mac +## + + +# globs +Makefile.in +*.userprefs +*.usertasks +config.make +config.status +aclocal.m4 +install-sh +autom4te.cache/ +*.tar.gz +tarballs/ +test-results/ + +# Mac bundle stuff +*.dmg +*.app + +# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk diff --git a/RhSolutions.ML.Builder/.vscode/launch.json b/RhSolutions.ML.Builder/.vscode/launch.json new file mode 100644 index 0000000..35b44e4 --- /dev/null +++ b/RhSolutions.ML.Builder/.vscode/launch.json @@ -0,0 +1,26 @@ +{ + "version": "0.2.0", + "configurations": [ + { + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/dotnet/vscode-csharp/blob/main/debugger-launchjson.md + "name": ".NET Core Launch (console)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/bin/Debug/net7.0/RhSolutions.Classifications.dll", + "args": [], + "cwd": "${workspaceFolder}", + // For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console + "console": "internalConsole", + "stopAtEntry": false + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach" + } + ] +} \ No newline at end of file diff --git a/RhSolutions.ML.Builder/.vscode/tasks.json b/RhSolutions.ML.Builder/.vscode/tasks.json new file mode 100644 index 0000000..a6f0b13 --- /dev/null +++ b/RhSolutions.ML.Builder/.vscode/tasks.json @@ -0,0 +1,41 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/RhSolutions.Classifications.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "publish", + "command": "dotnet", + "type": "process", + "args": [ + "publish", + "${workspaceFolder}/RhSolutions.Classifications.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "watch", + "command": "dotnet", + "type": "process", + "args": [ + "watch", + "run", + "--project", + "${workspaceFolder}/RhSolutions.Classifications.csproj" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/RhSolutions.ML.Builder/Data/train.tsv b/RhSolutions.ML.Builder/Data/train.tsv new file mode 100644 index 0000000..5d6f4ff --- /dev/null +++ b/RhSolutions.ML.Builder/Data/train.tsv @@ -0,0 +1,351 @@ +Name Type +Универсальн.труба RAUTITAN stabil 16,2х2,6 мм, бухта 100 м Труба stabil +Универсальн.труба RAUTITAN stabil 20х2,9 мм, бухта 100 м Труба stabil +Универсальн.труба RAUTITAN stabil 25х3,7 мм, бухта 50 м Труба stabil +Универсальн.труба RAUTITAN stabil 32х4,7 мм, бухта 25 м Труба stabil +Универсальн.труба RAUTITAN stabil 16,2х2,6 мм, прям.отрезки 5м Труба stabil +Универсальн.труба RAUTITAN stabil 20х2,9 мм, прям.отрезки 5м Труба stabil +Универсальн.труба RAUTITAN stabil 25х3,7 мм, прям.отрезки 5м Труба stabil +Универсальн.труба RAUTITAN stabil 32х4,7 мм, прям.отрезки 5м Труба stabil +Универсальн.труба RAUTITAN stabil 40х6,0 мм, прям.отрезки 5м Труба stabil +Унив.труба RAUTITAN flex 16x2,2, бухта 100м Труба flex +Унив.труба RAUTITAN flex 20x2,8, бухта 100м Труба flex +Унив.труба RAUTITAN flex 25x3,5, бухта 50м Труба flex +Унив.труба RAUTITAN flex 32x4,4, бухта 50м Труба flex +Унив.труба RAUTITAN flex 16x2,2, прям.отрезки 6м Труба flex +Унив.труба RAUTITAN flex 20x2,8, прям.отрезки 6м Труба flex +Унив.труба RAUTITAN flex 25x3,5, прям.отрезки 6м Труба flex +Унив.труба RAUTITAN flex 32x4,4, прям.отрезки 6м Труба flex +Унив.труба RAUTITAN flex 40x5,5, прям.отрезки 6м Труба flex +Унив.труба RAUTITAN flex 50x6,9, прям.отрезки 6м Труба flex +Унив.труба RAUTITAN flex 63x8,6, прям.отрезки 6м Труба flex +Унив.труба РЕХАУ FLEX 16x2,2, бухта 100м Труба flex +Унив.труба РЕХАУ FLEX 20x2,8, бухта 100м Труба flex +Унив.труба РЕХАУ FLEX 25x3,5, бухта 50м Труба flex +Унив.труба РЕХАУ FLEX 32x4,4, бухта 50м Труба flex +Унив. труба RAUTITAN pink+ 16х2,2 мм, бухта 120 м Труба pink +Унив. труба RAUTITAN pink+ 16х2,2 мм, прямые отрезки 6 м Труба pink +Унив. труба RAUTITAN pink+ 20х2,8 мм, бухта 120 м Труба pink +Унив. труба RAUTITAN pink+ 20х2,8 мм, прямые отрезки 6 м Труба pink +Унив. труба RAUTITAN pink+ 25х3,5 мм, бухта 50 м Труба pink +Унив. труба RAUTITAN pink+ 25х3,5 мм, прямые отрезки 6 м Труба pink +Унив. труба RAUTITAN pink+ 32х4,4 мм, бухта 50 м Труба pink +Унив. труба RAUTITAN pink+ 32х4,4 мм, прямые отрезки 6 м Труба pink +Унив. труба RAUTITAN pink+ 40х5,5 мм, прямые отрезки 6 м Труба pink +Унив. труба RAUTITAN pink+ 50х6,9 мм, прямые отрезки 6 м Труба pink +Унив. труба RAUTITAN pink+ 63х8,7 мм, прямые отрезки 6 м Труба pink +Отоп. труба RAUTITAN black 16х2,2 мм, бухта 200 м Труба black +Отоп. труба RAUTITAN black 20х2,8 мм, бухта 180 м Труба black +Отоп. труба RAUTITAN black 25х3,5 мм, бухта 100 м Труба black +Отоп.труба РЕХАУ BLACK 16х2,2 мм, бухта 200 м Труба black +Отоп.труба РЕХАУ BLACK 20х2,8 мм, бухта 180 м Труба black +Отоп.труба РЕХАУ BLACK 25х3,5 мм, бухта 100 м Труба black +Фиксирующий желоб для ПЭ-трубы 16/17 Фиксирующий желоб +Фиксирующий желоб для ПЭ-трубы 20 Фиксирующий желоб +Фиксирующий желоб для ПЭ-трубы 25 Фиксирующий желоб +Фиксирующий желоб для ПЭ-трубы 32 Фиксирующий желоб +Фиксирующий желоб для ПЭ-трубы 40 Фиксирующий желоб +Фиксирующий желоб для ПЭ-трубы 50 Фиксирующий желоб +Фиксирующий желоб для ПЭ-трубы 63 Фиксирующий желоб +Монтажная гильза 16 PX Монтажная гильза +Монтажная гильза 20 PX Монтажная гильза +Монтажная гильза 25 PX Монтажная гильза +Монтажная гильза 32 PX Монтажная гильза +Монтажная гильза 40 PX Монтажная гильза +Монтажная гильза 50 MX Монтажная гильза +Монтажная гильза 63 MX Монтажная гильза +Тройник равнопроходный 16-16-16 PX Тройник RAUTITAN +Тройник 16 Тройник RAUTITAN +Тройник 16-16-16 Тройник RAUTITAN +Тройник равнопроходный 20-20-20 PX Тройник RAUTITAN +Тройник 20 Тройник RAUTITAN +Тройник 20-20-20 Тройник RAUTITAN +Тройник равнопроходный 25-25-25 PX Тройник RAUTITAN +Тройник 25 Тройник RAUTITAN +Тройник 25-25-25 Тройник RAUTITAN +Тройник равнопроходный 32-32-32 PX Тройник RAUTITAN +Тройник 32 Тройник RAUTITAN +Тройник 32-32-32 Тройник RAUTITAN +Тройник равнопроходный 40-40-40 PX Тройник RAUTITAN +Тройник 40 Тройник RAUTITAN +Тройник 40-40-40 Тройник RAUTITAN +Тройник равнопроходный 50-50-50 RX+ Тройник RAUTITAN +Тройник 50 Тройник RAUTITAN +Тройник 50-50-50 Тройник RAUTITAN +Тройник равнопроходный 63-63-63 RX+ Тройник RAUTITAN +Тройник 63 Тройник RAUTITAN +Тройник 63-63-63 Тройник RAUTITAN +Проточный настенный угольник 16/16-Rp 1/2 длинный RX+ Проточный угольник +Проточный настенный угольник 20/20-Rp 1/2 длинный RX+ Проточный угольник +Проточный настенный угольник 25/25-Rp 1/2 длинный RX+ Проточный угольник +Проточный настенный угольник 16/16-Rp 1/2 короткий RX+ Проточный угольник +Проточный настенный угольник 20/20-Rp 1/2 короткий RX+ Проточный угольник +Проточный настенный угольник 16/20-Rp 1/2 короткий RX+ Проточный угольник +Проточный настенный угольник 20/16-Rp 1/2 короткий RX+ Проточный угольник +Проточный настенный угольник 25/25-Rp 1/2 короткий RX+ Проточный угольник +Тройник RAUTITAN RX+ с наружной резьбой 16-16-R 1/2 Тройник RAUTITAN резьбовой +Тройник RAUTITAN RX+ с наружной резьбой 20-20-R 1/2 Тройник RAUTITAN резьбовой +Тройник RAUTITAN RX+ с наружной резьбой 20-20-R 3/4 Тройник RAUTITAN резьбовой +Тройник с уменьшенным боковым проходом 20-16-20 PX Тройник RAUTITAN +Тройник с уменьшенным боковым проходом 25-16-25 PX Тройник RAUTITAN +Тройник с уменьшенным боковым проходом 25-20-25 PX Тройник RAUTITAN +Тройник с уменьшенным боковым проходом 32-16-32 PX Тройник RAUTITAN +Тройник с уменьшенным боковым проходом 32-20-32 PX Тройник RAUTITAN +Тройник с уменьшенным боковым проходом 32-25-32 PX Тройник RAUTITAN +Тройник с уменьшенным боковым проходом 40-20-40 PX Тройник RAUTITAN +Тройник с уменьшенным боковым проходом 40-25-40 PX Тройник RAUTITAN +Тройник с уменьшенным боковым проходом 40-32-40 PX Тройник RAUTITAN +Тройник с уменьшенным боковым проходом 50-20-50 RX+ Тройник RAUTITAN +Тройник с уменьшенным боковым проходом 50-25-50 RX+ Тройник RAUTITAN +Тройник с уменьшенным боковым проходом 50-32-50 RX+ Тройник RAUTITAN +Тройник с уменьшенным боковым проходом 50-40-50 RX+ Тройник RAUTITAN +Тройник с уменьшенным боковым проходом 63-25-63 RX+ Тройник RAUTITAN +Тройник с уменьшенным боковым проходом 63-32-63 RX+ Тройник RAUTITAN +Тройник с уменьшенным боковым проходом 63-40-63 RX+ Тройник RAUTITAN +Тройник с уменьшенным боковым проходом 63-50-63 RX+ Тройник RAUTITAN +Тройник с уменьшенным торцевым проходом 20-20-16 PX Тройник RAUTITAN +Тройник с уменьшенным торцевым проходом 25-25-16 PX Тройник RAUTITAN +Тройник с уменьшенным торцевым проходом 25-25-20 PX Тройник RAUTITAN +Тройник с уменьшенным торцевым проходом 32-32-20 PX Тройник RAUTITAN +Тройник с уменьшенным торцевым проходом 32-32-25 PX Тройник RAUTITAN +Тройник с уменьшенным боковым и торцевым проходами 20-16-16 PX Тройник RAUTITAN +Тройник с уменьшенным боковым и торцевым проходами 25-16-16 PX Тройник RAUTITAN +Тройник с уменьшенным боковым и торцевым проходами 25-16-20 PX Тройник RAUTITAN +Тройник с уменьшенным боковым и торцевым проходами 25-20-16 PX Тройник RAUTITAN +Тройник с уменьшенным боковым и торцевым проходами 25-20-20 PX Тройник RAUTITAN +Тройник с уменьшенным боковым и торцевым проходами 32-20-20 PX Тройник RAUTITAN +Тройник с уменьшенным боковым и торцевым проходами 32-20-25 PX Тройник RAUTITAN +Тройник с уменьшенным боковым и торцевым проходами 32-25-20 PX Тройник RAUTITAN +Тройник с уменьшенным боковым и торцевым проходами 32-25-25 PX Тройник RAUTITAN +Тройник с уменьшенным боковым и торцевым проходами 40-32-32 PX Тройник RAUTITAN +Тройник с уменьшенным боковым и торцевым проходами 50-32-40 RX+ Тройник RAUTITAN +Тройник с увеличенным боковым проходом 16-20-16 PX Тройник RAUTITAN +Тройник с увеличенным боковым проходом 16-25-16 PX Тройник RAUTITAN +Тройник с увеличенным боковым проходом 20-25-16 PX Тройник RAUTITAN +Тройник с увеличенным боковым проходом 20-25-20 PX Тройник RAUTITAN +Тройник с увеличенным боковым проходом 25-32-25 PX Тройник RAUTITAN +Тройник настенный с внутренней резьбой 16-Rp1/2-16 RX+ Тройник RAUTITAN резьбовой +Тройник настенный с внутренней резьбой 20-Rp1/2-16 RX+ Тройник RAUTITAN резьбовой +Тройник настенный с внутренней резьбой 20-Rp1/2-20 RX+ Тройник RAUTITAN резьбовой +Тройник с внутр. резьбой на боков. проходе 25-Rp 1/2-25 RX+ Тройник RAUTITAN резьбовой +Тройник с внутр. резьбой на боков. проходе 25-Rp 3/4-25 RX+ Тройник RAUTITAN резьбовой +Тройник с внутр. резьбой на боков. проходе 32-Rp 3/4-25 RX+ Тройник RAUTITAN резьбовой +Тройник с внутр. резьбой на боков. проходе 32-Rp 3/4-32 RX+ Тройник RAUTITAN резьбовой +Тройник с внутр. резьбой на боков. проходе 32-Rp 1-32 RX+ Тройник RAUTITAN резьбовой +Тройник с внутр. резьбой на боков. проходе 40-Rp 1-40 RX+ Тройник RAUTITAN резьбовой +Тройник с внутр. резьбой на боков. проходе 50-Rp 1-50 RX+ Тройник RAUTITAN резьбовой +Муфта соединительная равнопроходная 16 PX Муфта соединительная +Муфта соединительная равнопроходная 20 PX Муфта соединительная +Муфта соединительная равнопроходная 25 PX Муфта соединительная +Муфта соединительная равнопроходная 32 PX Муфта соединительная +Муфта соединительная равнопроходная 40 PX Муфта соединительная +Муфта соединительная равнопроходная 50 RХ+ Муфта соединительная +Муфта соединительная равнопроходная 63 RХ + Муфта соединительная +Муфта соединительная переходная 20-16 PX Муфта соединительная +Муфта соединительная переходная 25-16 PX Муфта соединительная +Муфта соединительная переходная 25-20 PX Муфта соединительная +Муфта соединительная переходная 32-25 PX Муфта соединительная +Муфта соединительная переходная 40-32 PX Муфта соединительная +Муфта соединительная переходная 40-25 RX+ Муфта соединительная +Муфта соединительная переходная 50-32 RX+ Муфта соединительная +Муфта соединительная переходная 50-40 RX+ Муфта соединительная +Муфта соединительная переходная 63-50 RX+ Муфта соединительная +Переходник с наружной резьбой 16-R 1/2 RX+ Переходник на наружную резьбу +Переходник с наружной резьбой 16-R 3/4 RX+ Переходник на наружную резьбу +Переходник с наружной резьбой 16-R 1 RX+ Переходник на наружную резьбу +Переходник с наружной резьбой 20-R 1/2 RX+ Переходник на наружную резьбу +Переходник с наружной резьбой 20-R 3/4 RX+ Переходник на наружную резьбу +Переходник с наружной резьбой 20-R 1 RX+ Переходник на наружную резьбу +Переходник с наружной резьбой 25-R 1/2 RX+ Переходник на наружную резьбу +Переходник с наружной резьбой 25-R 3/4 RX+ Переходник на наружную резьбу +Переходник с наружной резьбой 25-R 1 RX+ Переходник на наружную резьбу +Переходник с наружной резьбой 32-R 3/4 RX+ Переходник на наружную резьбу +Переходник с наружной резьбой 32-R 1 RX+ Переходник на наружную резьбу +Переходник с наружной резьбой 32-R 1 1/4 RX+ Переходник на наружную резьбу +Переходник с наружной резьбой 40-R 1 1/4 RX+ Переходник на наружную резьбу +Переходник с наружной резьбой 50-R 1 1/4 RX+ Переходник на наружную резьбу +Переходник с наружной резьбой 50-R 1 1/2 RX+ Переходник на наружную резьбу +Переходник с наружной резьбой 63-R 2 RX+ Переходник на наружную резьбу +Переходник с внутренней резьбой 16-Rp 1/2 RX+ Переходник на внутреннюю резьбу +Переходник с внутренней резьбой 20-Rp 1/2 RX+ Переходник на внутреннюю резьбу +Переходник с внутренней резьбой 20-Rp 3/4 RX+ Переходник на внутреннюю резьбу +Переходник с внутренней резьбой 25-Rp 1/2 RX+ Переходник на внутреннюю резьбу +Переходник с внутренней резьбой 25-Rp 3/4 RX+ Переходник на внутреннюю резьбу +Переходник с внутренней резьбой 25-Rp 1 RX+ Переходник на внутреннюю резьбу +Переходник с внутренней резьбой 32-Rp 3/4 RX+ Переходник на внутреннюю резьбу +Переходник с внутренней резьбой 32-Rр 1 RX+ Переходник на внутреннюю резьбу +Переходник с внутренней резьбой 40-Rр 1 1/4 RX+ Переходник на внутреннюю резьбу +Переходник с накидной гайкой 16-G 1/2 RX+ Переходник на накидную гайку +Переходник с накидной гайкой 16-G 3/4 RX+ Переходник на накидную гайку +Переходник с накидной гайкой 20-G 1/2 RX+ Переходник на накидную гайку +Переходник с накидной гайкой 20-G 3/4 RX+ Переходник на накидную гайку +Переходник с накидной гайкой 25-G 3/4 RX+ Переходник на накидную гайку +Переходник с накидной гайкой 25-G 1 RX+ Переходник на накидную гайку +Переходник с накидной гайкой 32-G 1 RX+ Переходник на накидную гайку +Переходник с накидной гайкой 32-G 1 1/4 RX+ Переходник на накидную гайку +Переходник с накидной гайкой 32-G 1 1/2 RX+ Переходник на накидную гайку +Переходник с накидной гайкой 40-G 1 1/2 RX+ Переходник на накидную гайку +Переходник с накидной гайкой 50-G 1 3/4 RX+ Переходник на накидную гайку +Переходник с накидной гайкой 63-G 2 3/8 RX+ Переходник на накидную гайку +Переходник на евроконус 16-G 3/4 Переходник на евроконус +Переходник на евроконус 20-G 3/4 Переходник на евроконус +Угольник 90°, 50 RX+ Угольник +Угольник 90°, 63 RX+ Угольник +Угольник 90°, 16 PX Угольник +Угольник 90°, 20 PX Угольник +Угольник 90°, 25 PX Угольник +Угольник 90°, 32 PX Угольник +Угольник 90°, 40 PX Угольник +Угольник 45°, 50 RX+ Угольник +Угольник 45°, 63 RX+ Угольник +Угольник 45°, 20 PX Угольник +Угольник 45°, 25 PX Угольник +Угольник 45°, 32 PX Угольник +Угольник 45°, 40 PX Угольник +Фиксатор поворота с кольцами 90°, 16 Фиксатор поворота +Фиксатор поворота с кольцами 90°, 20 Фиксатор поворота +Фиксатор поворота с кольцами 90°, 25 Фиксатор поворота +Фиксатор поворота с кольцами 90°, 32 Фиксатор поворота +Фиксатор поворота с кольцами 45°, 16 Фиксатор поворота +Фиксатор поворота с кольцами 45°, 20 Фиксатор поворота +Фиксатор поворота с кольцами 45°, 25 Фиксатор поворота +Фиксатор поворота с кольцами 45°, 32 Фиксатор поворота +Угольник-переходник с наружной резьбой 16-R 1/2 RX+ Угольник с наружной резьбой +Угольник-переходник с наружной резьбой 20-R 1/2 RX+ Угольник с наружной резьбой +Угольник-переходник с наружной резьбой 20-R 3/4 RX+ Угольник с наружной резьбой +Угольник-переходник с наружной резьбой 25-R 3/4 RX+ Угольник с наружной резьбой +Угольник-переходник с наружной резьбой 32-R 3/4 RX+ Угольник с наружной резьбой +Угольник-переходник с наружной резьбой 32-R 1 RX+ Угольник с наружной резьбой +Угольник-переходник с внутренней резьбой 16-Rp 1/2 RX+ Угольник с внутренней резьбой +Угольник-переходник с внутренней резьбой 16-Rp 3/4 RX+ Угольник с внутренней резьбой +Угольник-переходник с внутренней резьбой 20-Rp 1/2 RX+ Угольник с внутренней резьбой +Угольник-переходник с внутренней резьбой 20-Rp 3/4 RX+ Угольник с внутренней резьбой +Угольник-переходник с внутренней резьбой 25-Rp 1 RX+ Угольник с внутренней резьбой +Угольник настенный с внутр. резьбой 16-Rp 1/2 RX+ Угольник с внутренней резьбой +Угольник настенный с внутр. резьбой 20-Rp 1/2 RX+ Угольник с внутренней резьбой +Угольник настенный с внутр. резьбой 20-Rp 3/4 RX+ Угольник с внутренней резьбой +Угольник настенный с внутр. резьбой 25-Rp 3/4 RX+ Угольник с внутренней резьбой +Угольник настенный с длинным патрубком, внутр. резьба 16-Rp 1/2 RX+ Угольник с внутренней резьбой +Угольник настенный с длинным патрубком, внутр. резьба 20-Rp 1/2 RX+ Угольник с внутренней резьбой +Угольник настенный с наружной резьбой 16-R 1/2 RX+ Угольник с наружной резьбой +Угольник настенный с наружной резьбой 20-R 1/2 RX+ Угольник с наружной резьбой +Угольник настенный с наружной резьбой 20-R 3/4 RX+ Угольник с наружной резьбой +Угольник настенный с внутр. резьбой 16-Rp 1/2 длинный, 59 мм RX+ Угольник с внутренней резьбой +Угольник настенный с внутр. резьбой 20-Rp 1/2 длинный, 59 мм RX+ Угольник с внутренней резьбой +Угольник настенный с внутр. резьбой 16-Rp 1/2 длинный, 70 мм RX+ Угольник с внутренней резьбой +Угольник настенный с внутренней резьбой 20-Rp1/2 70мм RX+ Угольник с внутренней резьбой +Кронштейн, тип O 100 Кронштейн +Кронштейн, тип O 75 / 150 Кронштейн +Кронштейн, тип D в сборе Кронштейн +Кронштейн, тип Z 30 Кронштейн +Кронштейн, тип Z 42 Кронштейн +Кронштейн, тип Е Кронштейн +Кронштейн 75 / 150 Кронштейн +Распределительный коллектор G1 2 отвода G 3/4 Сборный коллектор +Распределительный коллектор G1 3 отвода G 3/4 Сборный коллектор +Распределительный коллектор G1 4 отвода G 3/4 Сборный коллектор +Трубка из. нерж. стали для подкл. радиатора, Г-образная 16/250 Трубка для радиатора +Трубка из. нерж. стали для подкл. радиатора, Г-образная 16/500 Трубка для радиатора +Трубка из. нерж. стали для подкл. радиатора, Г-образная 16/1000 Трубка для радиатора +Трубка из. нерж. стали для подкл. радиатора, Г-образная 20/250 Трубка для радиатора +Трубка из. нерж. стали для подкл. радиатора, Г-образная 20/500 Трубка для радиатора +Трубка из. нерж. стали для подкл. радиатора, Г-образная 20/1000 Трубка для радиатора +Комплект трубок из. нерж. стали для подкл. радиатора, Г-образ 16/250 Трубка для радиатора +Комплект трубок из. нерж. стали для подкл. радиатора, Г-образ 20/250 Трубка для радиатора +Трубка из. нерж. стали для подкл. радиатора, Т-образная 16/250 Трубка для радиатора +Трубка из. нерж. стали для подкл. радиатора, Т-образная 16/500 Трубка для радиатора +Трубка из. нерж. стали для подкл. радиатора, Т-образная 16/1000 Трубка для радиатора +Трубка из. нерж. стали для подкл. радиатора, Т-образная 20/250 Трубка для радиатора +Трубка из. нерж. стали для подкл. радиатора, Т-образная 20/500 Трубка для радиатора +Трубка из. нерж. стали для подкл. радиатора, Т-образная 20/1000 Трубка для радиатора +К-т двух резьбозажим. нипелей с нар.резьбой 1/2х3/4 (латунь) Ниппель +Резьбозажимное соединение для металлической трубки G 3/4 -15 Резьбозажимное для трубки +Пара шаровых кранов с соед. нип. G 1/2xG 3/4, прямой (никелирован.) Краны +Пара шаровых кранов с соед. нип. G 1/2xG 3/4, угловой (никелирован.) Краны +Распределительный коллектор HLV на 2 группы нерж. сталь Коллектор +Распределительный коллектор HLV на 3 групп нерж. сталь Коллектор +Распределительный коллектор HLV на 4 группы нерж. сталь Коллектор +Распределительный коллектор HLV на 5 групп нерж. сталь Коллектор +Распределительный коллектор HLV на 6 групп нерж. сталь Коллектор +Распределительный коллектор HLV на 7 групп нерж. сталь Коллектор +Распределительный коллектор HLV на 8 групп нерж. сталь Коллектор +Распределительный коллектор HLV на 9 групп нерж. сталь Коллектор +Распределительный коллектор HLV на 10 групп нерж. сталь Коллектор +Распределительный коллектор HLV на 11 групп нерж. сталь Коллектор +Распределительный коллектор HLV на 12 групп нерж. сталь Коллектор +Резьбозажимное соединение flex/pink 16х2,2xG3/4 Резьбозажимное для трубы +Резьбозажимное соединение stabil 16,2x2,6xG3/4 Резьбозажимное для трубы +Резьбозажимное соединение stabil 20x2,9xG3/4 Резьбозажимное для трубы +"Комплект двух прямых никелирован. шаровых кранов G1"" для коллекторов " Краны +"Комплект двух угловых никелирован. шаровых кранов G1"" для коллекторов " Краны +Шкаф коллекторный, встраиваемый, тип UP 110/450 белый Шкаф +Шкаф коллекторный, встраиваемый, тип UP 110/550, белый Шкаф +Шкаф коллекторный, встраиваемый, тип UP 110/750, белый Шкаф +Шкаф коллекторный, встраиваемый, тип UP 110/950, белый Шкаф +Шкаф коллекторный, встраиваемый, тип UP 110/1150, белый Шкаф +Шкаф коллекторный, встраиваемый, тип UP 110/1300, белый Шкаф +Шкаф коллекторный, приставной, тип AP 130/500 белый Шкаф +Шкаф коллекторный, приставной, тип AP 130/605, белый Шкаф +Шкаф коллекторный, приставной, тип AP 130/805, белый Шкаф +Шкаф коллекторный, приставной, тип AP 130/1005, белый Шкаф +Шкаф коллекторный, приставной, тип AP 130/1205, белый Шкаф +Шкаф коллекторный, приставной, тип AP 130/1353, белый Шкаф +Шкаф коллекторный, встраиваемый, тип UP 75/550 , белый Шкаф +Шкаф коллекторный, встраиваемый, тип UP 75/750, белый Шкаф +Шкаф коллекторный, встраиваемый, тип UP 75/950, белый Шкаф +Шкаф коллекторный, встраиваемый, тип UP 75/1150, белый Шкаф +Крюк с дюбелем для 1 трубы Крюк +Двойной крюк с дюбелем для 2-х труб Крюк +Двойной крюк с дюбелем для 2-х труб в изоляции Крюк +Фиксатор поворота трубы 16/17/90°, без колец (оцинк. сталь) Фиксатор поворота +Фиксатор поворота трубы 20/90°, без колец (оцинк. сталь) Фиксатор поворота +Фиксатор поворота трубы 25/90°, без колец (оцинк. сталь) Фиксатор поворота +Фиксатор поворота трубы 32/90°, с кольцами (оцинк. сталь) Фиксатор поворота +Фиксатор поворота трубы 16/17/45°, без колец (оцинк. сталь) Фиксатор поворота +Фиксатор поворота трубы 20/45°, без колец (оцинк. сталь) Фиксатор поворота +Фиксатор поворота трубы 25/45°, без колец (оцинк. сталь) Фиксатор поворота +Фиксатор поворота трубы 32/45°, с кольцами (оцинк. сталь) Фиксатор поворота +Пресс-втулка 16 Монтажная гильза +Пресс-втулка 20 Монтажная гильза +Пресс-втулка 25 Монтажная гильза +Пресс-втулка 32 Монтажная гильза +Пресс-втулка 40 Монтажная гильза +Пресс-втулка 50 Монтажная гильза +Пресс-втулка 63 Монтажная гильза +Тройник 40/40/45° Тройник RAUPIANO +Тройник 40/40/87° Тройник RAUPIANO +Тройник 50/40/45° Тройник RAUPIANO +Тройник 50/40/87° Тройник RAUPIANO +Тройник 50/50/45° Тройник RAUPIANO +Тройник 50/50/87° Тройник RAUPIANO +Тройник 75/50/45° Тройник RAUPIANO +Тройник 75/50/87° Тройник RAUPIANO +Тройник 75/75/45° Тройник RAUPIANO +Тройник 75/75/87° Тройник RAUPIANO +Тройник 90/50/45° Тройник RAUPIANO +Тройник 90/50/87° Тройник RAUPIANO +Тройник 90/75/45° Тройник RAUPIANO +Тройник 90/75/87° Тройник RAUPIANO +Тройник 90/90/45° Тройник RAUPIANO +Тройник 90/90/87° max flow (гидравл. оптимизированный радиус изгиба) Тройник RAUPIANO +Тройник 110/50/45° Тройник RAUPIANO +Тройник 110/50/87° Тройник RAUPIANO +Тройник 110/75/45° Тройник RAUPIANO +Тройник 110/75/87° Тройник RAUPIANO +Тройник 110/90/45° Тройник RAUPIANO +Тройник 110/90/87° Тройник RAUPIANO +Тройник 110/110/45° Тройник RAUPIANO +Тройник 110/110/87° max flow (гидравл. оптимизированный радиус изгиба) Тройник RAUPIANO +Тройник 125/110/45° Тройник RAUPIANO +Тройник 125/110/87° Тройник RAUPIANO +Тройник 125/125/45° Тройник RAUPIANO +Тройник 125/125/87° Тройник RAUPIANO +Тройник 160/110/45° Тройник RAUPIANO +Тройник 160/110/87° Тройник RAUPIANO +Тройник 160/125/45° Тройник RAUPIANO +Тройник 160/125/87° Тройник RAUPIANO +Тройник 160/160/45° Тройник RAUPIANO +Тройник 160/160/87° Тройник RAUPIANO +Тройник 200/160/45° Тройник RAUPIANO +Тройник 200/160/87° Тройник RAUPIANO +Тройник 200/200/45° Тройник RAUPIANO diff --git a/RhSolutions.ML.Builder/Models/model.zip b/RhSolutions.ML.Builder/Models/model.zip new file mode 100644 index 0000000000000000000000000000000000000000..7b7bb6985368c818c40f786202a0884289d7f497 GIT binary patch literal 47211 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
    6SY5_87jod_gu5xdEfC0Z>W zl|2#^$4pb3XK2f1Erx%SXtHXkTq{MF%dQohS@G)#-)juG1U1#;V!i#!Ov{lHU6^zB z&UlTdkS+)xDKuTSY-rGGLQ3ti<+>W;;T*cpKXpfdK5#*}(W1&vkBrojoRDRquBav> zA0jv6D=D_31Pcek&des+)=y45=Q&Se<*AUd0#o8dbFM0?Qd@S)$fP)&h#nlU2*0lr zp}~}vlC;astmM&Zv!%|lp+3E>_`BP?oPK-S4e5_zL8s67o)5Vt1wLoYlW~A*f;m_ag$erO#g8Sn^}UGoRvpfqqv^y1 ztV@%X3j2+9MNNT((~0(w%9y~qC@Dx6VrFP`O1=CBg|i$I^Tm$q&pOboQmF*RtH z*ZfEfhOV?jg(7d3;iJLiU&5@?E$1vZD(j`Red|yJlNJff6sOGwFL&%mZs{B1n=~~o zG)rPc%)gLa>aom-NmgJZK+*%WQsu?dT+x08A07X5)y|JeB6u=Fwid$#8~2 z+CBQ2*u@{f=0V<~C=X^Th}L~n02gRmut%HV%2|oxMJ#;LlV9E2{JcR-hR0`f!6HnAJ-_AE3*ac z28`o(9df9Z3k6ydZ1q~owaJM?Vr{>*j(do_8!Q2T;?IiK=xypY@0z|EkDy6dl3Mb? zByEzehdNbp&6vvjt+E_GaY2}AIGgMOvtL>n)~O*-kg#V#DxEK?sj1Zv&qiam>MVIz zzvUpww}+FeY248$dkWi5owIOi2EwjyBw}kr7B6$RIxQM>I8PQXJ3frAN!!L{+=y$} zfOhYQN=L%XhGTB&Y}ibfD9Jr%SIXTuM5qa-VX~@kq&N(IWl+d4rAW6@KA>vbukWC% zRXsWBglbD;w7hl@)r2(BbpLy?m#aYJQ-`~W&>^s%v!{tUYfhbHvy^&4wEYJMJ-V19 z>)P4^LW|V+{F0NM_LtSHV28FOu$8Q4VJ))Fv>CezZ}0EYKh@umn#O+@_Ev?BMbr=} z?+zy*YKmwM&f_Sh*}zGw%Si97DR6_B12GrCzNeIPXp*i$riO1cqBBRHw2b94T0xFP)1B@2;31yQJTPcLE;Ga$lajcc!=S9 z%XHS7)D`j8@-9xZv<}i|(q}(be6I=^?@YL%Q*Lp4ATE(NgR9 zQ4uLLqfNQRpNXQqweRtU38vD%@qN7kX-#I@Ms{kl<7}EquAF=(WJ8Ble4kFSK?>Nz zG*)a7ZtPa_R&El%I5RrZz%or$1ssbG0V%gn#4Ym#cu8DD6zP7Q@$oH&k#^D|!PqcA zv@h+rSXO1?AH%x;i?z25iZfWZg@*(Q?!g^`TX1&^P6+Or;7%Y6?l!nva3{FCySux) z3^2$gd+&SBKIg0YPTi{0^JAuJs%E;^^E}<}yH>xebNj7m3F+w==tl0y1B%oTqPrOB z^82b=buflcViu{AF&+YnT3YhU^KC>{-?{pj{ET2@uaB#@FZn9-WVvApeJSDPSE;F< zSVb#iBSU7D#PPAoBT$^WN3EC(}7SD0dm=qc!xzXZ>UxL#H_D;;PnI{ ze@*8~eI08iqPG38F!yOqm0{uvKh37^1v8JdKD ze6d=qIBXPs%q(XK$eC?X|Mj%+Q*U&qk%=8{SLe4kxbM<6)blIjc_LWHQGo`-;lWGv zVTDjoy?-)HOmN@5e-JM*`ZXn^nPxj&>t*bC&@Cc^HTqd)baP|^o3QmP)4_%Hd=v@W zVFi`y{>riLg!!B7wEjn z=J9_?U#HpM=<~&#__gwN?iW&#k%Hp{|KNPhT+P--w0Ff|%J=IHL`bFHm`QwVuAu59 z#`%wMy<(V$pBYDZSjSk0oTi^z=YDxO9YgMNUfMr7Sc|?%d4BJxqPKhnEd_JJf;Ih# zn-<8)3MlKn`>;46e$4)xS^wgE%}SF9Z2oe-*8=O=^+w>(sAUC@!M-Fx!}Y%4cIjjy z7RsLf(#H&f3;iSb|BBM|Vibhr4WSS3|5vzij{iidR%P^!^F@1^34zJ_v3F}dHTn2pvxla)hg$yd;wgD(ftaw>i>w$i@s z<9uK+7|m>c)^Ww;-d$o8yl!7M0@lYd$XiaT&}aYZ!8(`Oz}t!+`Cd8fb(A7N^qf-I z2_Lv~#yrbLu8=v5!uA>ITw!nQ{dUYHBTxw9yGX52-B7U4XOUsN7sS1D5~>{XzF0^~ z{2TvJqw(W^vtx2uxT_|73q#BQ4)xCYZ(&esR_I|tBRr#d@TaGtMcWb%4t=*fxj~7A z9#;^hBfeoop-&E_-vg(lqI9Jh9xKm{P~Ls#?&8vaTuTu^bNQa56D6&2x33g##Gm8? zIKT@Y9JA0Yhpyl@k!-DNMlrvHA%qH(-no@`#AkT5A1+4H@-i`zTVb#=`aD*8 zkC5BSj;srqUP^g)f{NdRG$;zp|K!K>JN6`Pow?SVaQ6t>{0z&>&X(MM=eP%wazp?< zm*$pGVW<3}PcP-|<#-?hx~^kaGfQipMrV{HIcBg4_0u-f3?igWtneGZ8Rm4gW!wJO zQczv#gNVJwp!0vH6uAB~24zaaf8`H>vWi-5bWYtJs;qk?9kuj52Kjq zT$o!+oktj7S+8E^OF4(Hp;~{o66d7*5R9E68qo1koW{C+eFM zUlp>t3cJOdyV+%9LyW6_=&33fg;|&k>BM+x*wQ1nBibUgGblWq*OFQ3&rn&xmGt0O zDx3s+F+4Fmk+o3e;CkVW@~}JP2BTkkbohsg$jDQ4GiDSfw1@p-tc8dL+y}=WYQpLOFdnYe&2yK2N zI41v7n6Z=f8AwnWkofxFW-U+mFS>sfy_vUg@xQ(QhgsSG>|XYN z?PUH#Hu(roI^ z)NhhtSVD~j^So=9+N#vfR7D*6pa?ZC$wTtNQ6A1U<-DfySH06;9(QUlciS&sc@pfF zq|xNQB9Xq*b|N4ikz+Adm4oaEMk5CV2gmPn8&zwsU7z{m2HxDt!UiX5sEoVe7sD#e zTK3n^w5!~E1E&?97DLdTN1DRODx`6VSV&7FldyeA-kxZJ{;x^=QBc{p>TIc_x zA<@6>iA|3jMetQZ3s4l0K}Cy}sIiEzlVRP$uo=c8|9Sy;)T(o52jr@09bHN06EfeE z+o1oTJ5FLrX?cf?zAYg+dA2Z~x}%AjY|Gc?I==jT`iJc$L71zT?ptA(%4~}A^=06Z zCeLl0LJ{1gDrS0I)VC3ACoYGMF)uT8ZH}RZ8E;wPo%_I*v*EVj_YVOJ4(Eq$2J}wU zRRqRP^6QfrXK^RRFlNpYv*48|0zcIM3P32MVb$Rq0D!ld^#2ine-n0VL97aIi`zc$4G&aMWJ+el4eu1GxO9RNWG-rtOU53=Fq?o*v`34R^FV?pnq#&* z<9k}QXs;)&7mmP77cEcpZtWm0v!$V;d1a!5EGjG1$C7&YAZt}`i=Q1hGfJ%@!;90g z^OLtZsRF7XDKQhn52EX@6OvW365v85`jeQW1VEr^f$dV2}}gH#|G!0&6a)Tgt$R zk6bep$~|8o%?B56;{051vHsjze>G16ex;YszJ&>aCS!NN5)Wr{e-pxS-h^-*A}h4$ zuTiNK-O!xJ&!|YMnbK$N}sX$pZ<`3Mb1DVOVD*dI)xL2V` zlf>`44uUl|8wJl}{#y>sEOKvTd;$QxpWXwQ{wEmzRW|=Q+n=r?3d=2$z+H&M_>=pi zX~mRMinHynAX{5ugpE2b*A(T-YZ+C;R?2*kS<0pA$wwyRU_;h25?E@9QC};w4nbxt zdv>*X&jqpz0GrBp}I>>ZmQZf=(+=-+b zD!;`)8Y=0gm+*6O+tHIp*I9Ac-=>cls!X#p(KFkPM6TpaPwYYgiibR}13ES@EFU!x zRZ}mru}h`iqWso`v2E(|u?DL-##s)>9&!+SA@(dr7=n8OW2pFk)E`qfuWg-`na&ka z4pm;Yf@@_32$Lg|R0&D!KI5|5-^y%$sHU!x;hJ5?vjkUn<;uP*fmP)JwI+0aRV_Ps zXqq}57}~q3-2S5ZH>uv5w>v>IDJ)yj5Bwb3V+pUY6Z(a)T2!FIKF(?FeQdYo#UP3d zjYU6GNVIdKpH@#!VT_|uWxXEN_3oQm+DtmBar7YRhX1?4ge3C1G9$QWyE#6)C!$J> zNt=0MzCFq_Mq4XAH=~|j2=BT)tt+4`Xj?c8iN9tLp4UXD_s}C0vv*HsRetxo0Dd^A zZe6M1vC`=$!=+Zb@1W23nUq$iqtE(3MkbIkMq_W-E{W=N_lDmcjV}smDph&F*EAOb z_EVoJ^&m0aqquVv{~S@4B(uwtsx@RT*sBgv!*=w60I`<@r1<&A1yA32!MtkoNXw>; z>iH!DZ|*ugBD&077C23;%-uMK4~#;AF&7Sh@~2V^EhKpmKXPsAC5iI(6i*x@BVMe2 z5{amRD0ZecTwhl=xRjbQ9_aL!g+gok2ahAeercF;8UIv!0;AJ(m{woVZ)WzcS&lXLBb$ zueW3X{!PIG*;OjqFKBOKG~Y^Pjc{4ZWI2ZIw-u*WxDOQN#U`PDnnCLYHb-~g#Ku{9 zkl(f%oj9n|e1k~bZLuOWDo|~RaJxKAkw`5l^p)jXSQCDF(UyLteW(sC$8^YT6y;xNwesvIUHwH1>q`mu0&wuF zc+9h#*U30rch^J7!WGRjm_9N%T?hiY$AaS`@PphhY=^mt*_+k0YE+GBZkP+{U<#Oz zGYAmgbs@XD(zh3si9vWcGC=z{Pn~8e=kIXz5@ZF~^LK1V;H_zPm{%X-nfK*=jC+f1|PF$|9pl? zPJOzUST3K-C}Z9uaSXq6`?T&!ZRCb>QtnoRre<_-F4OhsBL_@$l;^x7GrElK@W*$-}JYSBAmrZCzFaj7{;dFx(?jgGtO@K+mAGPEwB>ivub$^IRE-<)qF=V0=Z8L zlyKV@vA5Ze0(Nm8xBAQlgG7I-^Mm5dsZ9Tv>CgCnP#sAmVnok!_l%5aqPU>zj7@_O z^S^!rkQF$!aBkO|1a2cc;u<^}B2#w4!|tTqB*}Zqh%!E~YT$e`VEx;&;@*`hhNVkA zTwXocH($qJt$aau;I%HFb{6%7Ch0KoTR0j3~3>$e_$6Pc7^E*4m?Vc_&T52s~4>sT)lsNh;} z)vZ~B76N5~eV$^AvhRv$yUQ-4UWjNu!HiOHyDRey%+@EhuCcyz43i99W#hHEezrI# zD>FqS)l!()xJ2LsA!mLqjN6|O@nyop4tnP06Vayq$LJ?;Q(x}#l04hD@6ysy&~G06 zW&@yiY~4PLabS;l?3z_x7dDXGKvRa&flAZUJ~Fuxq`K-mMXo6PteHDy-C86LnLbIg zrEz&t*PJxmz1O91yXHKlsU#Y69youukAi6GYQsM-Ok3f45$2%&2&6SJ!M%b{leL{+ zb+yiJzATHJUQJK5omw^VLp_z9)q2u6g4Esjx^yp2t{%-Q@Yxn{I3I-~JA+e@IXY}; z@_;`9y*7^|Hs_^c4`buvbM6T=Pcy=*?smvma(aI5$SVregPzo$zn|I0<{#cX+3sOl ztv&;L-J19Cje>6OG%PD|B;o2loS4P0Q$MD>TE_wFm{HC+u={a1y4^F~jEA4iel9KB z9z2|^vmrt5+(CCtnv|!!0 zz6h(Y1&8o8-z8xyqzHW0Ci|WEZCB9zm(PklNw)kam(#8_7&j%STk+QADE4>@CyVl7;of}8X46sx#pn9AF)_llSr`dO2j zJ*2g(XT&JSnIhTEPbQL?Wc9~4g2H&(m-5Uz9A8#XJT4+M7FE)@X7AnljMRhsS~98D zGbx;(Ghev$42&QIiucc>;VoVj)AqJ*3>2nMH{n^y*3ex*dYF%Fd^EbNjSV$}1ADkr zWZiQwvEmhrjU};i^+MC#uEozM742oJ6iYU$-+o5P*Y^9B5}k@4v+-5Sx_K?oO>)D@ zg6WQzi|E7N%wfhL6?&&w>*s>vhbImGG6NSM)Lok(4vIo)F55h<{AKFz5ACVisY$^B zFuSJ=#v=#zx`OMGw$KTtiW3psCyZX3>HK zepEwSovZqf0%`U2Ev;hv1LxnZs;RT*i^qqvj)zy*#jRf9QR<_HFLiMDnCf1k@0sF% zrope=VXhm$n5NA^Fd|RA;BAF)!USAbJHW{AFAel>o9iGDuO`lW4j9vitf6R$MO7l_ zdIDx1E2d1R!Hal$4Qrusjs)Ke_V0>s_hA6-2A}@p(+$c1;4t*K?C9rkHkTk*-6gV7{AF{C%#< zSA(Z?HD1n4!7p(QT!e&G10?d6Qy*hRSHUw~u5-1$Hjc}icv5e>j5rk0Tr(Boo5-$3z%Io+GlTbw!`;{(GB&p1g6%6`>v0iKpecOhd_9bAZ2r+r0)D~?b+_#6d;DVBQ%oDlzy0YtFO}ob25JMrOHu)>- z7!-+TPUv^z8%g0U7Y%AZr{qid)BIpYHX8?9{v0WTGHcZ_PU~Z5o#mSxs85xZ_zJF# z%YqD49VS6ITO-BAA(_DQLZ`GAi(54oV4Yb??yl>M7BGmB7gBbmR6=&Dop?JI`~Vk#@4=A~aC`uFXQt)G*kHlGzrpi^OS&FtDi z*jPmRB~$bD?#wMH)?RQ#}u_oWu5`BWVg0OzEaSo@jx}#^lySG@V z_mMuj7A5?_hrj?A0rA}6d-GY?cpBJ;_+>AXRYo3UYXOA) zhNQ~-H#WkjXDlZ@^4rwg z+|*({B;MuV;&AT*A8Z|iz{j~!maJ1T<5`KY1<{*38P02P4f4pv{QEVl-zr@S zezPr`mvS!%QjnI@uVM?h9=EzbE1(Qug5P) z^8|6}-gWpYs5xzImD-zKa6ewsqp%g1m27RUciHFS5AKg&$Qs#P<}7&yD;0S6_gsAm z?$Zm}nKLId6Aje0cC<$fl?8td>#MddtxF_P9J{AIZMC&9di|nqn0dHmYXpTU5&y=+ z002kKPiyKIn(t|_ZR{$$>IUm83cffC60%sM>Gl;43Pz~R-Je>GMB>S@Rz8v8j4g|# zCnE_CqXv6X8@&5gi0c;3R>=OL9Okd60RX z>D(GFEgE|^|G-B?yWisl2eJ!y>RHLcopfeitoFo-N)xirJo~&oy1KMI0>ySYF;+79 za5s(r455^GC>n5b-?vz1QyII>>p$lI)Bn|`zMy(Xj(TO-z`JMLf6yy-lUoJ3br}8r z_Eg^JA+1_0ju1pbplZ8#-DP2wC_M(YjpGb^L|ESQO^!0uJ*(jU{F8Gv^HoMF1QM_w z|B3KZgz{Vy?_+SmpS!N4_9plwnqs8CK>z^Q>s)Nt=})e0%^b2+_nj5fUDUPvA`#CA z^K?ls{NcvdGARwJl(;be1|ZMs0<(toOolbu6gy)%?HyPnS|w#toQ}dMMdMjp|6Kfh zn&|}3NkFBKHPn{kQf`OxxfN9c#-l;8wcDKk($e~D#W+@#Fi~JIq&v4Vw0NXOO>vY| z*@@?GN3wVy#jX6>;bl6VXP`T~8HqMmaM^KpJu<#d-O?A0|8Nzw4jfI4&+MlCax;mM z3v7XQ+v6;8+H0gFLE9AUr*9L52-MvaK)!|t zitxQTHT-QB9gP)RXN(3f29AD9a30}AyAFB|`{T9TlZ}4fG6V`F_k8pKI=Y>9?S}c? zeWQN-Zr0uTkC!R&UgtKFI0Et3C8Y;3diupiTQB)d0#K%mKfZ0-vyGKw8Jg{h;X5A;kB1_(jNtlOPkZN?Pt`upzx#RL z+UmhsCnG`kPxUZ+QF*)J>t{6CFP(}Xx$TyW6{ddy|A>LgE{OiMg0o9!t*(E0_=RKU zBX)e#+BqSlP<;A8tyEe7J8!sbk)=aDx+YXq06d)cx=|KtvUIKiKC})*n7*d3dt-uG zV@2y=Y%D68)ORCRAol`HFda29EON4xVkP#A+6?*?7(}k3VriG@#8_u-lgd9L-yU*#YY~H{Tk%H~ zja*Bx^F$@tQaF@#62LUgYgc(BAW8hIr1Tez)-!n==j?*rI)ymyaetd`Y!_nfN5A{? zfSDc#b8a9L@uwt;yJi}RCG*`WVwDRSuS!Ty5H zJ_0Si*Mnz?AwlKs5%S>;5QxrR;?29Gmce!Mg3hPV!#&Xw93$G@RO2w{RI`ftF zUsPxFUHP5-nsKu64H4Hd#b;(f)llgj-Hg6`OZ+mI3K`8(1%V)GEjx9Yl|Gu+RKjj# zB4zYiyjX@?t)QS*UB)Bo)m945Dcu-vHF=g{AnU4W*Af_A2el+{q3=VqNh4S?L=$MB zACLaJu&b0P{DWtQNEzbzr_boIAGQ)Ga3Be%`gNctCcAJR0EkjhyJQLgN--&!=c&{M zoH(h2*45t@j681?>1Ve;2f5l2nfsaUH@}k>xXU`-0w9MB@Iw-dKIxlm)Bxc_o~Jt1 z;_)OQCT&_y-NBIP2BU#(xt*^nSttB=)Ll)9zyDkkU+{<`tRco^WeBeVAGtug?A+x?+9Yh<|xdP=_G@1&RDJSP$clpf=E+<1rwr>Lsz|FPJ6R zTb@1ikG#D#=d@2#(L)5VC$3TH2Ba&BXQIX&RlA~V2`knY=z3Ki)}|xwI-KQmoWOaI zWs&see*a$Ac951&$d_hNYgw1*9c? zJ{5f&kHp5A+$3ESf2uUg#`wsWyti6+tztb7i~n+wEczGsYNI351B-Y zU=;s64HvrG%1%~*LdV*#-q)!%oT~$ozYx# z&|g$wi5@#NJUyOC5z8xmVGYui>OrU>euS@r@P43SgKLt_hCJ9P^Ys@VceBWB9N{`y z>NAl~4;nqBkP3>S5(v%of=?(ec%G|`8aX^Uj6?-ebWH^^U;E)>v!p02R|_1Pl`W=S zey=}9FInmTx?l@vtzVMM^iG~}B^HHH1&b%_{&Ou5#y7K}KDq_^VpDL@o-8G4w^HOi zo)B4(NGtX$Xftv?hey)uysT)30x6|9*;srJkWH&Rc>F53@M^ZYZGXRtRLNFHL5(*2{d z5PNp_SiUfyWn8n;go3mS(&Fe&CjQdjNAck+V`H`|7jw67D-FY;biDY^r{O0cGkAp$C8Tu!jh1_B zSj-P1m;tp?+(=%(#cX0W%3$ z&4siCJ|jo^-0qM(Z9;G&ekg*3lrPtgzYm@=(Y4#cp(Z{xYn?%*TY5yug3` zJy08EA5;xY#b}Slc{a=2zsee=>x(T~)GFZ1p80=Dl9ATTfE5zS)n?sct#7EOaXh5p z}uahZW-D)<-k>~vr0-zAna3J&I z8B@ueo-O9j;=|RB4zHNGB!Tf8@2RaX-JOYTW&o_PFEn8h&E+fZH8E*)#a#`sfCB(- zjqM$Y$ltEJEHLvhVKTh{G_fp~f?K;d(=u-K59fvnz}@Rs=i$?~gNbTn2O*p9ng^tbeZYI6M!rdn-Q8_hjSU& z@>+z#bnoc?$y84$$#b1{PzuVIPr42AQ5;n;Rg^K2V_dCV^U0ge37V~t;YANvc)sO| zFi=33Jahf%8&?;EU~}nH7W=0MMb+f-XwS^0VUu=?}EEm|a~zHVXY zu>i((IwZ=E>$Dzbb8e zJ83MRWT;sMRt+B@jH$U`L53lbDE93TLWKQnZT;M>s|32ujc>$1Quvbd_>eP|NPjR> z|E7M!cDXbkZkzv9!4%Jam6(MbuF)YhQ}umsQNc` zBV*gu)G~c2^{7M?e3kl4pv~YMKb@{iReP~;gMRmP=yNoqOcla*qqKXERM{by=D@4c zh_iAz3Y@&TfQaO0_a{a57pJ1ixHzB(9hxU3^VYf54kP@!jixba*zy>-_J5IDl*3Xt zu1b8G@D@{X(@3GIT6r7Qh(f#E*OX%+$JTk8QUN1LRI&S0@;7XR0~K&;RX}%huVE9X z4E6Kd4nu^olx?(V0eI@#;b%gdEM(nd*XDLf10^jHo50t$q}*V9?evV6v=#oZbe<8rp$7*ty$<7qW7a(do=QHeu6?}?54`!5T(M_ zzveQ1IhEZ}drbiTqIqI-+nL4*4#^(Q{vp>SU4AW=$kf4G6eNhgv~VM3J+iEuG3`Dc zO6EHcphWeikE)aFlGs&u07AX zFn%||fBYVH>%#3l>!AfR{rTr@dQizd;neMYM36L=vdtR+_@6Ws4d?r~UB|x;ox_`c z1#YGgWnrBN4*Oi=0=x&5=bh5{^Z2WZ6F}F@-S(1wHau(Ha!K}svDe&`@%@fqo4yiM zo4~g`Q~GfHK1|7(40M=__g${pL}vck0a)fPLeG)U1Qi8qI-Ly1k*8P1_Zlj#kdj$; z`IGB-R*d^&amY%kSyIR_ClPNbjg;>tLHufdlN0{CeQy9epkA0nJ(8b(=5sDZ0_PP2 z+;?tsKiz{%7Hv6<8;|s%HV_~ybZU;s$Cz^B=Zfb3RD2~ymCbeBRSMDHyqCT+5jGEn zpNZ#2wUyOjH7*|*)CKTR0w*Zu+TA=xSUOI$& zmUMMm!H&`vzsfIhN1s|8+IHgQUR*E(g{B4`WAk!kcU|>m0Xx0cy6v#m^@A|R2gXVp zGjci}lInZ=OOmmrmt;5u$|eG@eFheSZ~3%VpDXr=t(F9nP=}z+3Gm+ie293W^D$qW z)x9rP38?b5miX4WFK;#Nz%<&4c8MW{69PUYY=7R*`s&}0A#mlh9l{LAv8JnAVgZ9R2RMcIQB=MQ&`$nXrVlQ z0cn%FcCD>Cru}Q^>9_~}(^*9}bRuuzD(BfD7y5j{(}4|P%mfsHvb^%m+Zk;h6J^>} zOGG6{6k~UdDr-{Uy{Xwho`4Bbs_jj}kL-d%_2?H5gaD2>yDjqawBY4m=rV=7?l-_5 zTpe8mFWj&snnw=6ZvQOXx1nnqO9YK9KPMy<%V=PPXXPVP4$mtD(bVxh3NIYw8y5mowIG}dR>Tqrv?LE zhdK!@TM;@{3`9n+7< zLfPHqox{(X+-&xox^Sy}h|m%e?!MQur_c`y?bp6(?uc@d8GH7v=Tp~cHV-PKJ(W*g zMd{E!$yzs#lIfM`3vyE!_djoQf+Btf-4C`dUxfL-KiuCT+Ch-sa)z4%rJjs!rQ+US z7BRa{fC|QVHH?9X*VRWYOc=4F1T946_qLkpOLZw1#wBv={Y+Y0_GEiAYLAx}Oo1L4 z^XUZ^0tyWdcZIjVZ~@L7E=wkau~g5sv}%s9-*;Rc8v^0KyuOqUE}4#FEeBGVvHP`G zcuOX7DFEAW3UEFPmAlJZkn7b= zS8_1AUPXlGC zk5=v-xrZOrYySMOl#6HycPncb{xl;{SLF|$MQAy?NFR$4db{W^Pw!PEqB&4gEOGIWZm~tt$#@j@hFLX69sO zRv)oxDq%Be>+q0!xI5a?Tr-R1p`xK!-erHYt~Y;t;Izbv7xGf(5}6Ed$DWJ49zMf< zla1$5LyKE&kQ2Kb1^!M*fQb(h^cio{O6pkkz5|L(JY4wj%O|~rr#o1uq{+F2STuOH zla#9@d5mu(yHRP1^&)Z&jE_b?D5`Pvpty>Y#4uvMgAPVoI?0NTJ^VosQVhh?UZ=jw z7L97nmr`2|#G$QD1Owm*e!l|)1bkifQlZht0Iu?S9)3wzy*pPo{R*jSV>;IEs4__Y zlmFDdUUJgd#(-j}w0O-RLH0G=1UP&}n>t-@It|q2gmJs8H|;jj6THD1Gwrr9eaoH|%-Rmc|m7p$4t`Rr3eeXwop%)>qp8lFIq60awW5|e?9*ODa#Oe}M zT#s>>CnE}oBz_3AUoz?EKITXTso}A#V`b~nlbzyqD2 zcKF->2y-N?J@s|$mHSw zkBg%{U(nu5l9&ac%DM%LL<^uVlT32K5Roto23N z!Xh&Hz(28z95?L)k5!oT;}RZZDZ&|K1db5tYqYb7{6_|`@~!%ZWaF0FB1~cPU^GM3 zw!<(HE90C9pmEdUqEitjrUnO~Bqat07ZwJHiPQ!MW|b#Den-CAbUhCi_NrKW+6QnP zXiG|WWn4Bj3zL6iu`5&%o(IKZigq_Pn&*m*Ly%If@gt5Q$(sWAzisK_(pmBqgl|uF>+uD>Dq0bf@&;W8M@4I{%zOz^faAN}lkwltOOhRQ$}D@jRO zzn$tdz?vIf0H^n6{G94DGy?qb$SELLZZ3lJsCsTw$9WlwXf20A(PZUcNtg9Wzs(Fv zl%$F;;ES`g#yg$c5}PmuQ%2NF2?_HVc zTwi8Cx^|#=*>1U(Qz^-~o6)0ydRy6^ij+K!TJabxEo&6XFu?Z=Rx&Td&4< zGRj!x2l`c)S|v&bCoG8Lc#ZlE30;as5;X5_Ss^|QeVPmN7MqtAB1X=SG+f%}6!T>2 zy=|y=W}H4HW;qk@>;|n4X{ui;$uXMO+SO_tTDA$jr!q(pXpW{3&%0pCf_T`Zf7pdN zibq%wI(OMjxEJ!RiJb|T$rOE2D>-NWw=uZIGgB!Z6 z;uQ$Z=7Zyue$6ybPX&F+M^lfLfQ|oJ(7ieH$X5` zl^VQ)Ns@wAOZ|d}rrtzgf5XT94A!V69TF-A+evbUhT48}SUU+aQv$b(o%}{2=}7Zj zzopwjU^ZULG5!umZxdwmIatQ%nu#$Fa9v0!~V`8pAA1p9C<}(%CnH?KlW4G_j+d)_P}+|y)M)8yoA&< ziuM(N-bZ;{Z3;F-r?{}d2%mI^wEvmu>N(D9n-J9l-{HxnI{(!CDPL<0wNweJyRAefo|;u^G`S%SJlZDxk8>oTkSF!X>IC0 zTs?!T{%7qnJCSxl8$xII)RHed44Fb_xEsBANJm93UV>KCI3}d3Q7V%ShGH^;Iu>5a zg+A^_l6w(f`0GheCU=lx+~I4$^y#Dn{kL#GA`Qdd9nl_fMBS?tiv)V$m`G`S4@x`R zytv1wNb(#xfCc=~Zk>-`Rla6R{$NeAA|A0qNiv>nltX=wxg3>6lk$$VrLUd-X~6^V z-3+$;!>>AaLLm|2XIFML>WAsb(92DA^aM3bKNCAWsdrq-4HFIXOQ_IpH`F~oSCn2Y zl-r+l|>hP)k=MwHLX0w)kDO{CjqqBW4bLWwo2o^+ljardjHDy z!0>)AZ@{aXx1eU>Rfl7W#c)hXV(gDJf>QRVk58hPJZi;dG;*=kBRgJe=xgZ*Mw(~C zKH8s(2A6{{ul8I~Ql3WKPY?LwpD^3#y&%ga+ZG|uFE8!l==K##n)Qy$`o%cJ)*>o4 znDb^JtC%_uqL-99{ynLeT8ILHd=g1pH${9NVlkpA=L_F%LfG4GHS8Y!1-O4IMBOY*Vq5u; z`%ogrQR!Pv%3D!|L$`m`Ewl`P=M>@C>&o%&au>@k?Z0pMwG+9SykUu>IL+!h{OsAm zR$lQ5V1r<-+g6IWTVVUCFrVV9E*jgG^P*zM$%>DwKl9=yF2RLgnphT2Goyy<`$0zt zaSi=~YD-RHjUO7@1|yV#PKIOg!F8pr3bIWLXob|F=XGRO`)6lB(JPbEtMTi{%R;n) z<_Sh7LH8hYn=L!ZwG5nBJDS*Q!zl`OPSQ`r9rY&!n@H+TRLTMs79FF6QJoRRD^bkH z&R#vhKNL@NRZ>bOhQpjANUv8oYec5Lf~k_&3j3~na^jLld~js|q9||x*h?qU*FgdY zEqnS9+k;YYx%ki|t4)j$c7yY%6Vvs_W#IXWj}O9>WysSZECek>MBsw9W%wKXhoOol zp=U6Yv`+L`6%$4NF4!-UNhiklQb$>8EP2llJhn-}b%=LKIV<6W-fWQ9OenybjkK`9 z)wtxbKNj8C{>begOMW-RZa6|2kbcPa$2J7xE<^W%4daFlQA`u8#qryFQ(feBqQE^6 zO{jnG1%LHj@}gq|foA%S>@hsqw}=W&f0bs7t6 zp`HH7IYm~5Q4CtB7z$U{hLLrRJSn$|nlIbj zYq4TW(eO>UOOR8$F5oQ~KQL_aHtSJOqK#rB5Hxy_)7)Ly0H#@B zL3tgsj|}yC>BUal_wATQyH3fKcm;0sNh`ZU$DV)c+r7o9$f^z60bj&BJ zrTw9DbSig4jSuR?d9P}XcG`1Mig*VZXDo_#EQ@)#`%Va6uO4~Cz)C{k(X@5K`7!GX z8d8AOHE!SVe%<-$TVrGkVZO-v@w+8BT(p%I)Tvcpk3gT#N#-~H`>~)W!wyQS^J9Ht8&(=_C%`-&vt|&#HqFQ#yh1f-`2O%8Iz9io$Sga8ie75;T zeh#{mgEwI<-bGnJaWlWLl`jzE9PkSK)LLWtRjBBK8wWc8e=JhIpyv8>4GLG@m9n>} z&MIaE( zS6j8+2FKINpf+GE-MHc|q-jBYfo#>*P!=p&_)xXVDun5Lx0H8#+sk<@mvwMg{Mk>Q zb-NTO#Y6pmmg4+RBci7#SDFBKq`b@F%N?ZaHg%7*@rA$Ms;JW+d*srP&>riqRO0~<-(1nnb7g6xLHckJdR^FG_REIT9Qh6;Eg0-q)5Y6?-=#+`lIFP?C1J3Rh$ zfQ&>v(6;U>GG)Se2v4VGxykC=IIfKm4sL6JiH25}XFEvoTrBFc%Tmut)Rym#q4T2aF>w`0*zAe<8kE1LMXVE_` zuUdB7^0sg}VTk}6mbl)zn{5e|Q=Kz@bMSWGl}1+v3$NBy4(-PVBe7+IiZc_ij=HC1`Kf=Kl$?*fqm1Mq0E3+I@{5g-dK@Tgl2 z*Zq_eY9D+0c~KG_yn&%#O6t+X60x`|wIBzp@WYNXHGB0B!%?A_Dj73H*-)^jat=AA zHCDlz4y!Vxp)c)g&{uwT;?!*1Sjt?3t0UMjOmgCz>F_SU{5S`W`AdOY1O1Q`?AQyO zkOP%~quwn1TBD;z)n0_VF4JM@+m+d%i^qWrwSv{jYTh_)&0bVe?JGR>5hR^}_t$hp z!1a0rOA-dOTJA@wUkq^;N&yh!lJ6vVoTAKy-r-s+q((^^{y?>|IDFUW;LU^r)sKgp zY6+a&r}Tky@}#Z`6jPPGWlg`bhK|4(;c0Tk!9rAtmiaF^f&cbDL9 zjk`AP?yf6)=P);O=FXW{uj=ituKK&XdVOoHExmVl zukX`6VBLb9c6ysuC29|HgP@{Qc2H+`l>ptshca)=4MRE2&wXlh=R5ylp?g;|ml=vl zHlGUM8fD?-w~F_Y>!6%$TNLzRY!IjK)FZr5DvxjNs$vBa``eE-i8UK6$i~M2G_#NN ztg3xHAs?hz*~C|%Y@F_)!Y|{S%QuEZT9>fG9Vh^t`2m95B7E_Q82IlXY(h~=;{eOF zZ&G=Fv$#X*UWglKP#%DGm|qnTcI2+xMAweh@TSPV9dNu|^+#pXhCeRC^+Rk*&xJ{nA67~CRes^qeB0U_*xM{`9r~nEtvXPbf&D34qn+%ysfu*v}Jauvn z_$}revri|LR09loVJqg>CBKSA+Q;9rJZYLel;IvtGuov(M7gM{!-R(%b}7ox;ovC| zhykAuk2#pw1$$AKN9pHn<+i2^tR);66V{^Aung$x(08Jif;kku$qvOt7X?K4Gc#AM zG*!QyXKdwiNORv*UBa1u#EV6vUAwKas!ZYQ7d{}gb{);eXw0NZdNF2#M(mC>A<&f; z^R>V&2fYNjXEd?Ud^$wwN~udiv*Ux>sChnD&uF25~}KpOnIBh@n;d z4V7m*>H4rU8O3qw;#WEo70#(0GU(=S$?!A%LAkCgH;P;ztGihX^9}5kf8%Z0c$GPr zJ+ePA6~l}}i*2cVx~nd9TGSH68ZEkSZ`~!2$Dnz>r74Xoz9@<77lg>t!iNf?<@EyS zpKfb4#A}*)Xod%D0|G{xG$?U_&T~y7vyu@`h5_~i2K`@etrQ6hL-B-PctcgR0c;Nh z0IyA0)o`i80h~eUB|~@zR$mPIX#??ss(NiMb-(5=5(js|y(2!O7v|H?~_xYzNog7nwrn;A=jrq zh^o{Xm92g)g+vkVi_kL%sp6KRhG}pdE%@!4xS$BnBN8X_l}LB213VCfj*!&)8MEie zj+=1MkHV1xh!F%tw&2oq8>fr6W-Ut0q?pbGQ7_1AH0`dfyf?O^2IF5vM6C8nYb_{A z;MnVyt@n@Px56|F5|I!a;CaAf>Fg3*c8&;rXXYEbiP6kdUTPt(=P)7SLuIHR>9(V% z6LB?Rzb|V3xQQ)M%ZdbDUYV50q{ch=#neeWxsy^hQCteKpTrnjgWXs@f`%O-+t`-E zCQ@FWhdBs6hucyIU+h5IPIr;Dz2r*EUg2_yD^7NU0jZEE3t1{bY`C%)t#the3=XK90$>Bdi$tDbY?p*Ke)CS2c|n1(S5^C(b% zjkM}z_A)iskg%*~xR8Zhx|L2=R1v(WrhiALl2l>iD4OrRfXDE64MnXS`$-o)?UT#= zz`XlyMT$8uY856!3*U)x@~(Mn5s#q$?sxZf$9hEX#9R+Z^4m}%&x{=56)-$NK7&3t z(pV%=J*TjE1P3AIDha}(T;uRxNkud3S<&i@f~NBNE&@Cim+UmV|Z{tfzF>t8! zG4o2i21=3k^U~ll)kdkYYDulwmmONI`r#(VRYA^l{``V8E?iT}ve2nkUvWQ`eZ(?5 z@hn!NKAXUH`>U%=65OiAVQ?seMO8xCoUu6I}aa656JQUri>v0oy=- zbKD1l46Ci$8eUJm*DNDr8<9?zyB}lq?aCJIbI!fhr>1^8d(5m6dh=XrAeA#8)TTC7K-xl&J+WSpM z$PC&y5sVMMsOo(#g_3rby~MREs{poA76Lu{=gRli@mv1D5}MdebF1Svbs{M z26V)6rnJITn;a9S9a(9Vw-r_pL!zy4na-E! zI%}H6#d2MhZ#XXa9Gd>*z3BM1vB+DS6|Wy(O(|tFEWDN3LdmkmC_+XChlWH^Ae7*! zj_DO!Tj{jgs^bBAJFsfkI8#o`jX}}2JK3YTWmFl5t#E+}%F;)$TJp!yt!#UxjhK1P z;-PB0=ENlxH}h?nUa?nVVX>O}#(RfzqjsZ_4^9q7?zQpsz=eA!DbHwzvp$;d`hEMP zV9Bk)xsxI~C3;=yZyc#k4giA;kN|%t9=(BC=wh+#WEC2>q*hJd#`d%ai?(Ahq+ynG z=!St}&?c)vQS8$wi_<9y-`=J_>1#BLs8-}kEw6T!OR`v#`URfY86Xk1ZVa~3@dx## z#yFQcvkDc(B)$^%E{7V}%Q@gTMM%pdrB*Fd4sRAcoAKv3CuRN33?+)11l($t=uT@RPNSCPO{}NX=ZgLD^CB zj?%!$_ITszAl_9TO8Fr!&?sjO7K_wK7YVmtOSgZVYD|<~7$}b#*unaOzsx3IXF~A9 z&E5JuLEPSdZFIaM- zcrw2 z71{BdWK45_xlp` z8Rl=ap3us;aDGc2rx=%N9B*w(o!ARdbf@b`g9ymcMht{! z5vwm;UNaRNiCaOih<)8eljA`C4(*Jo%2>f=BBC!Mw7gaW*94tk)QIQ;-qaeJZN&@j zKdNp%hTbIZO!hHNS=bcAo4Lkh4%j4nxO`i!o3q?HXg6wpjkSm{=wjDN&pv|hw9yT` zWB%mvyO42rmWt99^|9qTOdV|_oU95pivaO^EQf{#GK=pp z-7X!4kO!@89rnzM%XKxwBekc%wUnW6=GIS~Ctz_LNly-qvb#IzjrjA?NNG!xqg4Io zyvX78WuTzpaNdKT=$?@5-RRsTljKo7I+mt`jOk2y#KJ~^q&JA%znSZnH@d{WzTvv< zOC^qJ*SJAY^JNYZV_ zuq_J)*MO+cQ=f%kLV&ka`E@Lbu!drfI@;qX05;JnfK%HM^0oZtZLhR;uxK$p1*5Q< zbZ|2ZOG6y;8=P)JnUrJ5b!?DusfwqSN#D4}N3@Wn-pE92tJ-qt?E&JuNXEXSfMTUa zmVBGJ2c+`4{wmfI=9|$~W`g|O{OXHsJX`$pk4NotH98uL8)?;oLS7J3q2G0JW{=G* z(EX$MWa|Z@Msf;=5YiwdPY$9IvYYxgaHWc0r>W9UeVbG+RX9Ll?-GM*AK4(8&OO9# z!O-YQm#Z(twsJ85&=gnoY*2lKDkN*r%=-{mcdCd;c{WS^XcPu(o|=>!A0B$ujdj~l zw$$Vw=C~<~R)m97XGgssxLuZt0-KlL^~$KW=i* z<JE_nijT&Y6iEW6QIcywaCw5Q*e^dk{yb0#n zj@kZNAjxc~1Y+JpRIx%HT#Yy$%Jx$zUA2#V0 zsJ}>4Uy)zNJI$u>(XzQC$Q!FPW?j#E{JS<6GqG8GcX@?_vrFnEocebZ^G~HBKe{k$ zPiiD2QDC%Vov#YV7)DS9zS(NcCt9pqRzik&ulAQKSm|M4^#gukKN^=))$F2Y+n*vqCw|r;o^6V?WA)+wn zPb6q_`l3BTt7H;op$#&@01e@fBz|0asvz3{T=HK%5}Os#+y|~UGuA{<-zT*TrmL!S zlr48eM#Zk7JGt<@r*0AB&x~?c72d@j*yKCSpLNwHt^``EF}LxprAuWgd{!F?M_nds z_LofM73~O~)H~R&9EyspBy&C9Wp$z++I_u+zA*0sDZ}oXN=MrUCMBjGwovnX-Q&h5 zUnp4$FFGmy={=VFXD2OKP1G?9|KO1Fota+Uf2TeqXckr~ob0!Bw2*j@wNB8wk${QW$AVQ17e!~B zRoO8Dq1vsODgBxL8mC(mp4m$}f{T5ElY;+9IfRK=m$}Y%HM>54h+!;f9a!C&}vv&TJyXSRW2f@{5flP3x$m?YY(cc4D=S4#@d^lc`rre@y3J2NS zan30ll19fqdIS@}JM~zPn33+dNf=En*|EW0g9QeZBA<@HTz2I zj7?RHuH@zSgx}Aao_8A=tLTMDgh1M24<;(KIN^(%Yq;X#m5R<)z$(%+k@j(|i+i3p z;kSnXw>;u5DZ7rRB`=n!Z;H-FX!+&DeH{Suk3aN7MGMkvnJx5V& zlncD4-YGqw%>7^>RM2%B^=2oXNvHzToR(-{=*3t8IkmV;PTp8z&05_idmcAe^lG7c zbGhEMz6}N|sc~6f#x@3YAKJ(s-$w~6mZibd$Pqd>9vRPT>qmQh$(wJNGbM?+x3<#d%>PI??gwzGUeB1?uHm;ScS49Z#}UUWwY+>^zf~btvu(Y$dCK zR7_1qao14np|I6~*P9P-@jPb^_0gbpQtDlf<0IYP&Fs9P*%|1t0j0cxB+iu2f6co? zb$#Oi;8{C{ywP(Csu--LwC!ka-TslSJaU5jUP=Zqbm?W_r6ckw94N7Z*T+?;4*y}m zdryP0ZjHwaHJrT*W!Hf7?8~-3cIywBge{&%6a3ppO~m6%#d{60vG#`i||M}I>91N3?;>x zYKoKqh-hIe>7i>$X!r&r&hi4wILNs0ao4RYqhrY#PBHQe;b!^4r{*7;Oeg&4&Fo5(xmP>e(ee=j-;lzNfk$A{@Z{~I4d;%e z#gM0*c*(^1=e6bYOXkmn1W{2BUP`%ran@DV7!~x*(GE_ta3aK49M{$?yojLuh_!Li z+7@(LY9Xs@+PU(nPr7G5hgv}&T9R>KHG(AHP$hr3lsYEy-Jj|6C7_Sp*=dgYMoL_J zO&~1qYJvT(&vUVm^yCc4$*K&SRTE|An3>9>uvft;5zL3;1n^y_28bj57Ux10C8 z>3x^#R_+o+&e0uYVL0z+D)+GsPn2G{yh<#1dC#;fE;ga(7%LsSiz=7)lHCWFhO4tL zaD#EoeDd^g@cO#U6{03fiP<>Wz5;cJ`ZP?!Ae;+QxUKO01Fv1^A#hwY!(2x;o+T>@ z^2pAUzgJ1R4<0wNQy*`>7Xx`G!b@&oT#ZVZc(_&3KmKH1A z;n0Ypuxg%5?|n+zwLmgw0p@bX`%))uL`2mG4zXvZZk$venA#S>QxFMK$z$-7ca~_- zb)CjW3%{p~plsfX=$~20D^Rf`qkK z#QDtG;i?WR)BV-~31gWfc{oSb0qtEK&5eB3x7y596GuCo8agkr$jl-_&*c14T)xdG zy^|*rkgGO!cU<+MgCDIJ&tiQej`Du_IzR*=dgXPLv-l)WuC>|3Jfp5oaS6iS<81b> zpLvh=gld>|7+`URfwwr0WwBNG;DIWICId#4$cw=aKkiHcR&p=D)RMMYRvO7)dEIfS zgP+p%Q{t)qtEu@w^=a*wQ5k}$#ME>_n=GvQ09z2gY{GQdA!>UX;p@sk1Huji&{Ct(Y@lRC?-TlV;@t`RPH_ydXB<`cTNXyxG}o5VAd>h%0`sw!{s*M+ypS zv~V2yk^tmMv_>Fj>qf(LP7NhxgOQ#Zm;KxvAdus$gf&nxo)gf=H;qTD(ei_!A^_%S zcyrW5E)4j!$=HkM%yGFW&i`|t%JL>XzIMRNd;lm#fw$k6K-Jeg+ej5o z`wWn7F-d7rmVh;_w5?XrN$QLhTPlnQseO8?QFHYp^!H-EEp|19%B-ys?{Mg)aKjcn z+dwEl;YQY@FzzPC+~#+psLl417G)0-2Rk@SpkrRZ94NME-9pHjg2!(9^O2s zDbqX08w$yi^y#HmLi28f96p4Wd|>k`Jt8-oA`;p5fL$(`xjK;Oek#~i?SvPUW#0je zoO5c3)t}XqOBSkFnDr36AWLK#HDoF8Mh&{GqXyhx4u}#hnM& zT0AkwZaMgu=pSbT@fgXWdSX@OoS?5M)1C7%#?rkw9+#QE{ch;;xu$K^@6XH?r+d?KL8P6kEeBq-@Ka*Ji)9Jp6bJ?mvMr z6oWuRD84HK4MJ7DDBk>BjB6dX_=D21l4ljOnm3>4+O$&Id!ezF`}NnRZ(fnMxM~jqiM*V&BeeC6nv2lP%G=iwKH0FqRG;^b zj^u8}T72y1cnsp@^TK@OylZV)B`V9APf~7(51@VlU=6p^?!-UDF@RAFv`=(f-u38q zUEk$KEFO9*=A)P^palLp7_p7Da+OkE$yz@;#Fbv+-B)|J0jmq6T?XyABt9ZD)-r&6 zfvEmOqM>cKkoMd`eQ4Gk)yInVNV+(Vh19N(2$2J}tX|_@VOR z(vO}LAS7{$Y>i-GS_--0sOxG1>q%$^vT&Q86m~jX?Vm!T#eMMQ2BCL%jh;+jKT(Fl zmYbPa8<=0}Vmw(>-9=Ya`8NJI`SyrpeeCq4ARr;SnNb&U`ULgo!iE9=DaB)OLBm^c zefVE88UKO#x?G;uwo?G!8^PDF+F<{Sx=J2~fl!G^XJ-a#B5ZZAmjnumXfoqz^beMM zFJ~ppl&X!|EYR?EH_j|+n2aCPhdv7C2WKp5A4ML8hl*Kxze|#+&59ykHtmde8Vdy# zv<)hI32veUFOMo8i$EQ=x~-+X64?ArZZ{Gjb2C_1?T623j}bkd80Nq^Tm7%F zKmUO&yIigs(I1>ME>1=+uG<$qemxwVSo-VGh=JcwFi=T^9M)F}?*LIgVU_9`5%F{< z^E00lkQPG0Br zpSaApBSlv9ER1M9v1rfC-)Bu%^;Um>!Od!I5~Dv*CNil?XYn!AAH-xCTqq|a9Kk3e zS)RWxAQJ@1bG?KlQr#IefsnR1Q+ zIY)pdb(-iLJ)ep`YK=F4fep2|goP-;PSAkhCCTgwC9DuN+$pu59jv21 z_$2TeT!!@GH*^Seur+812SHXfNG*MLCh#M0EfNG4`2Oeizv_<6ZA<|+CbmFTV+Tib zTN`>OH>c-T$}MQ1SHNBpf>{a#|6~G8So)tAH!(hwRaUh%)HiUp(sytNDjPdkJN`4c zK7i(J33!3o0%zsVaQWb8!A{#an%Fv6|FtLqBk&J!|2~YKN5>r;syzvgUrmF9{1-6(p|kMsZ_#CBWc*2z{yetq3-s1| zFpAiJz@>uz+qi#N-=E_aoI4-K!$3f|VnRR|{wdxF@U#E!{9kwBKZ}?7zcHrTUJ$== zMu32@1=C9X*`ZHhnt=a%4*haObR93HfWVm%2ltHnpE8t0^gr&{?ayhVf{zh`SVOXKj;0lD_;DUc7K_P=O>|`Ry|Ap!s>sq*M2`h{A_8Z|HSGq ky?eeN|7j<_>>s;xc`3->x9SkM;F}&Cn8*tJ3IxQz0a}ajO#lD@ literal 0 HcmV?d00001 diff --git a/RhSolutions.ML.Builder/Product.cs b/RhSolutions.ML.Builder/Product.cs new file mode 100644 index 0000000..99040fc --- /dev/null +++ b/RhSolutions.ML.Builder/Product.cs @@ -0,0 +1,16 @@ +using Microsoft.ML.Data; +namespace RhSolutions.ML; + +public class Product +{ + [LoadColumn(0)] + public string? Name { get; set; } + [LoadColumn(1)] + public string? Type { get; set; } +} + +public class TypePrediction +{ + [ColumnName("PredictedLabel")] + public string? Type { get; set; } +} \ No newline at end of file diff --git a/RhSolutions.ML.Builder/Program.cs b/RhSolutions.ML.Builder/Program.cs new file mode 100644 index 0000000..898e872 --- /dev/null +++ b/RhSolutions.ML.Builder/Program.cs @@ -0,0 +1,42 @@ +using Microsoft.ML; + +namespace RhSolutions.ML.Builder +{ + public class Program + { + private static string _appPath = Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]) ?? "."; + private static MLContext _mlContext = new MLContext(seed: 0); + public static void Main() + { + var _trainDataView = _mlContext.Data.LoadFromTextFile( + Path.Combine(_appPath, "..", "..", "..", "Data", "train.tsv"), hasHeader: true); + var pipeline = ProcessData(); + BuildAndTrainModel(_trainDataView, pipeline, out ITransformer trainedModel); + SaveModelAsFile(_mlContext, _trainDataView.Schema, trainedModel); + } + + private static IEstimator ProcessData() + { + var pipeline = _mlContext.Transforms.Conversion.MapValueToKey(inputColumnName: "Type", outputColumnName: "Label") + .Append(_mlContext.Transforms.Text.FeaturizeText(inputColumnName: "Name", outputColumnName: "NameFeaturized")) + .Append(_mlContext.Transforms.Concatenate("Features", "NameFeaturized")) + .AppendCacheCheckpoint(_mlContext); + return pipeline; + } + + private static IEstimator BuildAndTrainModel(IDataView trainingDataView, IEstimator pipeline, out ITransformer trainedModel) + { + var trainingPipeline = pipeline.Append(_mlContext.MulticlassClassification.Trainers.SdcaMaximumEntropy("Label", "Features")) + .Append(_mlContext.Transforms.Conversion.MapKeyToValue("PredictedLabel")); + + trainedModel = trainingPipeline.Fit(trainingDataView); + return trainingPipeline; + } + + private static void SaveModelAsFile(MLContext mlContext, DataViewSchema trainingDataViewSchema, ITransformer model) + { + mlContext.Model.Save(model, trainingDataViewSchema, + Path.Combine(_appPath, "..", "..", "..", "Models", "model.zip")); + } + } +} \ No newline at end of file diff --git a/RhSolutions.ML.Builder/RhSolutions.ML.Builder.csproj b/RhSolutions.ML.Builder/RhSolutions.ML.Builder.csproj new file mode 100644 index 0000000..75b0dcc --- /dev/null +++ b/RhSolutions.ML.Builder/RhSolutions.ML.Builder.csproj @@ -0,0 +1,18 @@ + + + + Exe + net7.0 + enable + enable + + + + + + + + PreserveNewest + + + diff --git a/RhSolutions.ML.Tests/RhSolutions.ML.Tests.csproj b/RhSolutions.ML.Tests/RhSolutions.ML.Tests.csproj new file mode 100644 index 0000000..697d9a0 --- /dev/null +++ b/RhSolutions.ML.Tests/RhSolutions.ML.Tests.csproj @@ -0,0 +1,25 @@ + + + + net7.0 + enable + enable + + false + true + + + + + + + + + + + + + + + + diff --git a/RhSolutions.ML.Tests/Tests.cs b/RhSolutions.ML.Tests/Tests.cs new file mode 100644 index 0000000..e8203a0 --- /dev/null +++ b/RhSolutions.ML.Tests/Tests.cs @@ -0,0 +1,59 @@ +namespace RhSolutions.ML.Tests; + +public class Tests +{ + private static string _appPath = Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]) ?? "."; + private static string _dataPath = Path.Combine(_appPath, "..", "..", "..", ".." + ,"RhSolutions.ML.Builder" , "Models", "model.zip"); + private MLContext _mlContext; + private PredictionEngine _predEngine; + + [SetUp] + public void Setup() + { + _mlContext = new MLContext(seed: 0); + ITransformer loadedNodel = _mlContext.Model.Load(_dataPath, out var _); + _predEngine = _mlContext.Model.CreatePredictionEngine(loadedNodel); + } + + [TestCase("Гильза 16")] + [TestCase("Пресс-втулка")] + public void SleevesTest(string name) + { + Product p = new() + { + Name = name + }; + var prediction = _predEngine.Predict(p); + Assert.That(prediction.Type, Is.EqualTo("Монтажная гильза")); + } + + [TestCase("Тройник 20")] + [TestCase("Тройник 20-16-16")] + [TestCase("Тройник 20х20х20")] + [TestCase("Тройник 32*32*32")] + [TestCase("Тройник 50-50-32")] + public void TPieceTest(string name) + { + Product p = new() + { + Name = name + }; + var prediction = _predEngine.Predict(p); + Assert.That(prediction.Type, Is.EqualTo("Тройник RAUTITAN")); + } + + [TestCase("Тройник 50/50/45")] + [TestCase("Тройник 110 110 45")] + [TestCase("Тройник 50 50 87")] + [TestCase("Тройник 50 50 45")] + public void TPiecePianoTest(string name) + { + Product p = new() + { + Name = name + }; + var prediction = _predEngine.Predict(p); + Assert.That(prediction.Type, Is.EqualTo("Тройник RAUPIANO")); + } +} \ No newline at end of file diff --git a/RhSolutions.ML.Tests/Usings.cs b/RhSolutions.ML.Tests/Usings.cs new file mode 100644 index 0000000..38d77d5 --- /dev/null +++ b/RhSolutions.ML.Tests/Usings.cs @@ -0,0 +1,2 @@ +global using NUnit.Framework; +global using Microsoft.ML; \ No newline at end of file diff --git a/RhSolutions.ML.sln b/RhSolutions.ML.sln new file mode 100644 index 0000000..ec0bbab --- /dev/null +++ b/RhSolutions.ML.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.6.33815.320 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RhSolutions.ML.Builder", "RhSolutions.ML.Builder\RhSolutions.ML.Builder.csproj", "{0ADAA6BD-87CB-4F92-83B2-6C3788634F31}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RhSolutions.ML.Tests", "RhSolutions.ML.Tests\RhSolutions.ML.Tests.csproj", "{E21FC75D-A7E6-4BC2-AFC5-9E36715240FA}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0ADAA6BD-87CB-4F92-83B2-6C3788634F31}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0ADAA6BD-87CB-4F92-83B2-6C3788634F31}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0ADAA6BD-87CB-4F92-83B2-6C3788634F31}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0ADAA6BD-87CB-4F92-83B2-6C3788634F31}.Release|Any CPU.Build.0 = Release|Any CPU + {E21FC75D-A7E6-4BC2-AFC5-9E36715240FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E21FC75D-A7E6-4BC2-AFC5-9E36715240FA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E21FC75D-A7E6-4BC2-AFC5-9E36715240FA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E21FC75D-A7E6-4BC2-AFC5-9E36715240FA}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {113E4C47-4B6F-4FC3-A0E8-9ABCAB65668F} + EndGlobalSection +EndGlobal