ืฉื™ื ื•ื™ ื”ื’ื“ืจื•ืช ื”ืชื•ื›ื ื™ืช ืชื•ืš ืฉืžื™ืจืช ืคืจืžื˜ืจื™ื ืื™ืฉื™ื™ื

ืคืจื”ื™ืกื˜ื•ืจื™ื”

ืืจื’ื•ืŸ ืจืคื•ืื™ ืื—ื“ ื”ื˜ืžื™ืข ืคืชืจื•ื ื•ืช ื”ืžื‘ื•ืกืกื™ื ืขืœ ืฉืจืชื™ Orthanc PACS ื•ืœืงื•ื— Radiant DICOM. ื‘ืžื”ืœืš ื”ื”ื’ื“ืจื”, ื’ื™ืœื™ื ื• ืฉื›ืœ ืœืงื•ื— DICOM ื—ื™ื™ื‘ ืœื”ื™ื•ืช ืžืชื•ืืจ ื‘ืฉืจืชื™ PACS ื‘ืื•ืคืŸ ื”ื‘ื:

  • ืฉื ื”ืœืงื•ื—
  • ืฉื AE (ื—ื™ื™ื‘ ืœื”ื™ื•ืช ื™ื™ื—ื•ื“ื™)
  • ื™ืฆื™ืืช TCP ืฉื ืคืชื—ืช ืื•ื˜ื•ืžื˜ื™ืช ื‘ืฆื“ ื”ืœืงื•ื— ื•ืžืงื‘ืœืช ืกืงืจื™ DICOM ืžืฉืจืช ื”-PACS (ื›ืœื•ืžืจ, ื”ืฉืจืช ื“ื•ื—ืฃ ืื•ืชื ืœื›ื™ื•ื•ืŸ ื”ืœืงื•ื— - ืžืชื—ื™ืœ ืงื•ื“ื ืืช ื”ื—ื™ื‘ื•ืจ)
  • ื›ืชื•ื‘ืช IP

ืœืื—ืจ ื”ืงืžืช Radiant, ื”ืœืงื•ื—ื•ืช ืงื™ื‘ืœื• ืืช ื”ื—ื•ืžืจ ื”ื‘ื ืœืžื—ืฉื‘ื”: ืขื‘ื•ืจ ื›ืœ ืœืงื•ื—, ื”ื’ื“ืจืช ื”ืชื•ื›ื ื” ืขื ื”ืคืจืžื˜ืจื™ื ื”ื "ืœ ื”ื‘ื™ืื” ืœืžื™ืœื•ื™ ื”ืงื•ื‘ืฅ pacs.xml, ืฉื”ื™ื” ืžืžื•ืงื ื‘ืคืจื•ืคื™ืœ ื”ืžืฉืชืžืฉ (ื ืชื™ื‘: %APPDATA%RadiantViewerpacs.xml). ื™ื—ื“ ืขื ื–ืืช, ื”ืชืฆื•ืจื” ืฉืœ ืœืงื•ื— ืื—ื“ ืฉื•ื ื” ืžื”ืื—ืจ ื‘ืฉื ื™ ืคืจืžื˜ืจื™ื ืœืคื—ื•ืช (ืฉื ื”-AE ืฉื•ื ื” ืขื‘ื•ืจ ื›ื•ืœื, ื•ื”ืคื•ืจื˜ ื”ื•ื ื‘ืขืฆื ื–ื”ื”, ื—ื•ืฅ ืžืœืงื•ื—ื•ืช ืžืกื•ืฃ ื”ืคื•ืขืœื™ื ืขืœ ืื•ืชื• ืฉืจืช - ืฉื ื’ื ื”ื™ื• ืœืคื•ืจื˜ื™ื ืœื”ืงืฆื•ืช ืฉื•ื ื”).

ื“ื•ื’ืžื” ืœืงื•ื‘ืฅ pacs.xml ืžืืช ืงืฉืจ:

ื‘ืžืฉืš ื›ื—ืฆื™ ืฉื ื” ื”ื›ืœ ื”ื™ื” ื‘ืกื“ืจ, ื”ืžืขืจื›ืช ื”ืชื—ื™ืœื” ืœืขื‘ื•ื“... ื•ืื– ื–ื” ื”ื’ื™ืข ืืœื™ื ื• โ€œืžืชื—ืช ืœืžื™ื ืื‘ื ื™ืยป:

  • ืขืœื™ื ื• ืœื”ืคืขื™ืœ ืžืกืคืจ ืฉืจืชื™ PACS ื—ื“ืฉื™ื ืฉื™ื—ืœื™ืคื• ืืช ื”ื™ืฉื ื™ื (ืฉื ื”ื—ืœ ืœื”ื™ื’ืžืจ ืฉื˜ื— ื”ื“ื™ืกืง). ืฉืจืชื™ PACS ื‘ืžื›ื•ื ื•ืช ื•ื™ืจื˜ื•ืืœื™ื•ืช, ืื‘ืœ ืœื ืขืœ ื–ื” ืื ื—ื ื• ืžื“ื‘ืจื™ื;
  • ืขืœื™ื ื• ืœืฉื ื•ืช ื‘ืื•ืคืŸ ืžืจื›ื–ื™ ืชืฆื•ืจื•ืช ื™ื™ื—ื•ื“ื™ื•ืช (ืขื ืฉื ื™ ืคืจืžื˜ืจื™ื ืฉื•ื ื™ื) ื‘-200 ืžื›ื•ื ื•ืช (ืžืกืคืจืŸ ื’ื“ืœ ื‘ืื•ืคืŸ ืงื‘ื•ืข);
  • ื‘ื”ืชื—ืฉื‘ ื‘ืงืฆื‘ ื”ื’ื™ื“ื•ืœ ืฉืœ ื”ื™ืงืคื™ ื”ืกืงืจื™ื, ื™ืฉ ืฆื•ืจืš ื‘ืคืชืจื•ืŸ ืœื ืจืง ืคืขื ืื—ืช, ืืœื ืžืฉื•ื›ืคืœ ื•ืงื‘ื•ืข (ืœื“ื•ื’ืžื”, ืื—ืช ืœ-1-3 ื—ื•ื“ืฉื™ื).

ื”ืคืชืจื•ืŸ ื ืžืฆื ืœืžื˜ื”.

ื‘ื—ื™ืจืช ื›ืœื™ื ืœืคืชืจื•ืŸ ื‘ืขื™ื”

ื‘ื”ืชื—ืœื”, ื”ื™ื• ื ื™ืกื™ื•ื ื•ืช ืœืžืฆื•ื ืคืชืจื•ืŸ ื›ืœืฉื”ื• ืฉื™ืฉื ื” ืืช ืงื•ื‘ืฅ pacs.xml ื‘ืฆื“ ื”ืœืงื•ื— ื•ื™ื‘ืฆืข ืฉื™ื ื•ื™ื™ื ื‘ืจืฉื™ืžืช ืฉืจืชื™ PACS ืžื‘ืœื™ ืœื”ืฉืคื™ืข ืขืœ ืฉื AE ื•ื”ื’ื“ืจื•ืช ื™ืฆื™ืืช TCP. ืœืงื•ื—ื•ืช Windows ื‘ืื•ืชื” ืชืงื•ืคื” ื”ืชื‘ืกืกื• ื’ื ืขืœ Windows XP ื•ื’ื ืขืœ Windows 7 - ืื– ื”ื™ื• ื ื™ืกื™ื•ื ื•ืช ืœื›ืชื•ื‘ ืžืฉื”ื• ื›ื–ื” ืขืœ ื‘ืกื™ืก VBScript. ืืš ืื‘ื•ื™, ืœื ื ื™ืชืŸ ื”ื™ื” ืœืฉืœื•ื˜ ื‘ืžืฉื™ืžื” ื›ื–ื•, ื‘ืฉืœ ื—ื•ืกืจ ื”ื ื™ืกื™ื•ืŸ ื”ืžื•ื—ืœื˜ ื‘ื›ืชื™ื‘ืช ื›ืœ ื“ื‘ืจ ืžื•ืจื›ื‘ ื•ืžืงื™ืฃ ื‘ืฉืคื” ื–ื•. ื’ื ื”ื ื™ืกื™ื•ื ื•ืช ืœืžืฆื•ื ื•ืœืฉื›ืชื•ื‘ ืœื ืฆืœื—ื• (ื™ืฉ ืœืฆื™ื™ืŸ ืฉื›ื‘ืจ ื”ื™ื™ืชื” ืœื™ ืชื•ื›ื ื™ืช ืื—ืจืช ื‘ืจืืฉ, ืื– ืœื ื”ืชืขืกืงืชื™ ืขื VBScript ื™ื•ืชืจ ืž-3-4 ืฉืขื•ืช).

ื‘ืกื•ืคื• ืฉืœ ื“ื‘ืจ ื”ื’ืขืชื™ ืœืคืชืจื•ืŸ ื”ื‘ื:

  • ื‘ืืžืฆืขื•ืช ืžื“ื™ื ื™ื•ืช ืงื‘ื•ืฆืชื™ืช, ืืกื•ืฃ ืืช ื›ืœ ืงื‘ืฆื™ pacs.xml ื‘ืžืงื•ื ืื—ื“ ื‘ื›ืœ ืฉืจืช ื‘ืžืฉืื‘ ืจืฉืช;
  • ืฉื ื” ืงื‘ืฆื™ื ื‘ื”ืžื•ื ื™ื”ื (ื›ื‘ืจ ื”ื™ื” ืœื™ ื ื™ืกื™ื•ืŸ ื‘ืคืชืจื•ืŸ ื‘ืขื™ื•ืช ื›ืืœื” ื‘ืืžืฆืขื•ืช Perl);
  • ื”ืฉืชืžืฉ ื’ื ื‘ืžื“ื™ื ื™ื•ืช ืงื‘ื•ืฆืชื™ืช ื›ื“ื™ ืœืขื“ื›ืŸ ืืช ื”ื’ื“ืจื•ืช ื”ืœืงื•ื—.

ืื™ืกื•ืฃ ืงื‘ืฆื™ื ื‘ืืžืฆืขื•ืช ืžื“ื™ื ื™ื•ืช ืงื‘ื•ืฆืชื™ืช

ื”ื—ืœืง ื”ืคืฉื•ื˜ ื‘ื™ื•ืชืจ ื”ื•ื ืฉื›ืืฉืจ ืœืงื•ื— ื ื›ื ืก ืœืคืจื•ืคื™ืœ ืฉืœื•, ื”ื•ื, ืขื ื–ื›ื•ื™ื•ืชื™ื•, ืžื‘ืฆืข ืงื•ื‘ืฅ .bat ืžืกื•ื™ื, ื”ืื•ืžืจ:

echo off
If exist %APPDATA%RadiantViewerpacs.xml copy %APPDATA%RadiantViewerpacs.xml srv.test.localpconfigs$pacs-%COMPUTERNAME%-%USERNAME%.xml

ืœืคื™ื›ืš, ืงื‘ืฆื™ pacs.xml ื™ืฆื˜ื‘ืจื• ื‘ืฉืจืช ื‘ืžืฉืื‘ ื ืกืชืจ, ืฉืฉืžื• ืžื›ื™ืœ ืžื™ื“ืข ืžืื™ื–ื” ืžื—ืฉื‘ ื•ืžืื™ื–ื” ืžืฉืชืžืฉ ื”ืชืฆื•ืจื” ื”ื–ื• ื”ื•ืขืชืงื”.

ื”ื“ื‘ืจ ื”ืงืฉื” ื‘ื™ื•ืชืจ ื”ื™ื” ืœื—ื›ื•ืช ืขื“ ืฉื”ืžื“ื™ื ื™ื•ืช ื”ื–ื• ืชืขื‘ื•ื“ ืขื‘ื•ืจ ื›ืœ ื”ืžืฉืชืžืฉื™ื.

ืฉื™ื ื•ื™ ืชืฆื•ืจื•ืช ื‘ืืžืฆืขื•ืช ืกืงืจื™ืคื˜ Perl

ืื ื• ื ืฆื˜ืจืš ืคืจืœ ืคืขื™ืœ ืขื‘ื•ืจ Windows ืž-ActiveState, ื›ืžื• ื’ื ืžื•ื“ื•ืœ XML::Writer, ืฉื ื™ืชืŸ ืœื”ืชืงื™ืŸ ื‘ืืžืฆืขื•ืช ื”ืคืงื•ื“ื” ppm ืœื”ืชืงื™ืŸ XML-Writer.

ื”ืชืกืจื™ื˜ ืขืฆืžื• ื”ืชื‘ืจืจ ื›ืคืฉื•ื˜ ืœืžื“ื™:

use XML::Writer;
 
# ะžั‚ะบั€ั‹ะฒะฐะตะผ ะฟะฐะฟะบัƒ ั ะพั‚ั‡ะตั‚ะฐะผะธ, ะพะฑั€ะฐะฑะฐั‚ั‹ะฒะฐะตะผ ััะฟะธัะพะบ (ัƒะดะฐะปัะตะผ ะปะธัˆะฝะตะต):
	$report_dir = "C:Perl64WORKPACS-xml3";
	opendir(DIR, "$report_dir") or die "ะะต ะผะพะณัƒ ะพั‚ะบั€ั‹ั‚ัŒ ะฟะฐะฟะบัƒ ั ะพั‚ั‡ะตั‚ะฐะผะธ!";
	@report_files = readdir DIR;
	shift (@report_files); # ัƒะดะฐะปัะตะผ ั‚ะพั‡ะบัƒ ะธะท ัะปะตะผะตะฝั‚ะพะฒ ะผะฐััะธะฒะฐ (.)
	shift (@report_files); # ัƒะดะฐะปัะตะผ ะดะฒะต ั‚ะพั‡ะบะธ ะธะท ัะปะตะผะตะฝั‚ะพะฒ ะผะฐััะธะฒะฐ (..)
#	print "@report_files";
	closedir(DIR);
 
# ะะฐั‡ะธะฝะฐะตะผ ะพะฑั€ะฐะฑะฐั‚ั‹ะฒะฐั‚ัŒ ั„ะฐะนะปั‹ - ะฟะพ ะพะดะฝะพะผัƒ ะทะฐ ั€ะฐะท. ะัƒะถะฝะพ ัั‡ะธั‚ะฐั‚ัŒ ะฟะฐั€ะฐะผะตั‚ั€ AET ะธ ะฝะพะผะตั€ ะฟะพั€ั‚ะฐ ะฒ ะฟะตั€ะตะผะตะฝะฝั‹ะต.
foreach $analiz_file (@report_files) 
{
	$full_path_to_file="C:Perl64WORKPACS-xml3".$analiz_file;
	open (INFO, $full_path_to_file);
 
	while ($line = <INFO>)
	{
		# ะŸะตั€ะตะผะตะฝะฝั‹ะต $aet ะธ $port ัะพะดะตั€ะถะฐั‚ ัƒะฝะธะบะฐะปัŒะฝั‹ะต ะดะฐะฝะฝั‹ะต ะดะปั ะบะฐะถะดะพะณะพ XML ั„ะฐะนะปะฐ:
		my ($other1, $aet, $other2, $port, $other3) = split /"/, $line, 5;
		# ะ•ัะปะธ ะฒัั‚ั€ะตั‡ะฐะตั‚ัั ัั‚ั€ะพะบะฐ listener - ั‚ะพ ะผั‹ ะดะพัˆะปะธ ะดะพ ะฝัƒะถะฝะพะน ัั‚ั€ะพั‡ะบะธ ะธ ะผะพะถะฝะพ ั„ะพั€ะผะธั€ะพะฒะฐั‚ัŒ ะฝะพะฒั‹ะน XML:
		if ($other1 =~ 'listener')
			{
				# ะคะพั€ะผะธั€ัƒะตะผ ะฝะพะฒั‹ะน XML c ะฝัƒะถะฝั‹ะผะธ ะฟะพะปัะผะธ ะธ ะดะฐะฝะฝั‹ะผะธ:
				my $writer = XML::Writer->new(OUTPUT => 'self', DATA_MODE => 1, DATA_INDENT => 2, );
				$writer->xmlDecl('utf-8');
				$writer->startTag('pacs');
				$writer->startTag('listener', ae => $aet, port => $port);
				$writer->endTag();
				$writer->startTag('hosts');
				$writer->startTag('host', name => 'MRT', ae => 'ORTHANC', ip => 'XX.YY.214.17', ts => '1.2.840.10008.1.2.1', port => '4242', maxassoc => '1', allpres => '0', search => '1', protocol => '1', searchcharset => '', wildcards => '3', carets => '0');
				$writer->endTag();
				$writer->startTag('host', name => 'KT', ae => 'ORTHANC2', ip => 'XX.YY.215.253', ts => '1.2.840.10008.1.2.1', port => '4242', maxassoc => '1', allpres => '0', search => '1', protocol => '1', searchcharset => '', wildcards => '3', carets => '0');
				$writer->endTag();
				$writer->startTag('host', name => 'R', ae => 'ORTHANC3', ip => 'XX.YY.215.252', ts => '1.2.840.10008.1.2.1', port => '4242', maxassoc => '1', allpres => '0', search => '1', protocol => '1', searchcharset => '', wildcards => '3', carets => '0');
				$writer->endTag();
				$writer->startTag('host', name => 'KT-20180501-20180831', ae => 'ORTHANC4', ip => 'XX.YY.215.251', ts => '1.2.840.10008.1.2.1', port => '4242', maxassoc => '1', allpres => '0', search => '1', protocol => '1', searchcharset => '', wildcards => '3', carets => '0');
				$writer->endTag();
				$writer->startTag('host', name => 'KT-20180901-20181130', ae => 'ORTHANC5', ip => 'XX.YY.215.250', ts => '1.2.840.10008.1.2.1', port => '4242', maxassoc => '1', allpres => '0', search => '1', protocol => '1', searchcharset => '', wildcards => '3', carets => '0');
				$writer->endTag();
				$writer->endTag('hosts');
				$writer->startTag('presets');
				$writer->endTag();
				$writer->startTag('lastsearch', dt => '4', mfid => '1048592');
				$writer->endTag();
				$writer->endTag('pacs');
 
				# ะŸะพะผะตั‰ะฐะตะผ ะณะพั‚ะพะฒั‹ะน XML ะฒ ะฟะตั€ะตะผะตะฝะฝัƒัŽ:
				my $xml = $writer->end();
				# ะŸะพะดะณะพั‚ะฐะฒะปะธะฒะฐะตะผ ั„ะฐะนะป ะดะปั ะฟะตั€ะตะทะฐะฟะธัะธ:
				$rewritexml = $full_path_to_file;
				# ะŸะตั€ะตะฟะธัั‹ะฒะฐะตะผ XML ั„ะฐะนะปั‹ ะฝะพะฒั‹ะผะธ ะดะฐะฝะฝั‹ะผะธ:
				open (NEWXML, ">$rewritexml");
				print NEWXML $xml;
				close (NEWXML);				
			}
	}
 
}

ืขืงืจื•ืŸ ืคืขื•ืœืชื•:

  • ืื ื• ืคื•ืชื—ื™ื ืืช ื”ืกืคืจื™ื™ื” ื‘ื” ืืกืคื ื• ืชืฆื•ืจื•ืช pacs.xml ืžืœืงื•ื—ื•ืช ื•ืžืžืงืžื™ื ืืช ืจืฉื™ืžืช ื”ืงื‘ืฆื™ื ื‘ืžืขืจืš ืฉืœ ืกืงืœืจื™ื (@report_files);
  • ื‘ืœื•ืœืื”, ืื ื• ืžืขื‘ื“ื™ื ืงื•ื‘ืฅ ืื—ื“ ื‘ื›ืœ ืคืขื ื•ืงื•ืจืื™ื ืื•ืชื• ืฉื•ืจื” ืื—ืจ ืฉื•ืจื”;
  • ื‘ืืžืฆืขื•ืช ืคื™ืฆื•ืœ, ืื ื• ืžืคืฆืœื™ื ื›ืœ ืฉื•ืจื” ืœ-5 ื—ืœืงื™ื, ืชื•ืš ืฉื™ืžื•ืฉ ื‘ืžื™ืจื›ืื•ืช ื›ืžืคืจื™ื“;
  • ืื ื• ืžื•ืฆืื™ื ืฉื•ืจื” ืขื ื”ืžื™ืœื” ืžืื–ื™ืŸ ื•ืžืžืงืžื™ื ื ืชื•ื ื™ื ื™ื™ื—ื•ื“ื™ื™ื ืขื‘ื•ืจ ื›ืœ ืงื•ื‘ืฅ (ืฉื ืœืงื•ื— AE ื•ืžืกืคืจ ื™ืฆื™ืืช TCP) ืœืฉื ื™ ืžืฉืชื ื™ื;
  • ืœืื—ืจ ืžื›ืŸ, ืื ื• ืคืฉื•ื˜ ื™ื•ืฆืจื™ื ืงื•ื‘ืฅ XML ื—ื“ืฉ, ืžื›ื ื™ืกื™ื ืืœื™ื• ืคืจืžื˜ืจื™ื ื™ื™ื—ื•ื“ื™ื™ื ื•ืื– ืžื›ื ื™ืกื™ื ืืช ื”ืžืกืคืจ ื”ื ื“ืจืฉ ืฉืœ ืฉืจืชื™ PACS ืขื ื”ืคืจืžื˜ืจื™ื ืฉืœื”ื - ื”ึธื”ึตืŸ. ื‘ืฉื‘ื™ืœ ืžื” ื”ื›ืœ ื”ืชื—ื™ืœ)
  • ืื ื• ืžืฉื›ืชื‘ื™ื ืืช ืงื•ื‘ืฅ ื”-XML ื”ื—ื“ืฉ ืขืœ ื”ื™ืฉืŸ.

ื™ืฉ ืœืฆื™ื™ืŸ ืฉืœืžืขืฉื”, ืื ื™ ืœื ืžืฉืชืžืฉ ื‘ืกืงืจื™ืคื˜ ื”ื–ื” ื‘ืื•ืคืŸ ืื•ื˜ื•ืžื˜ื™ ืœื—ืœื•ื˜ื™ืŸ - ืœืžืขืฉื”, ืื ื™ ืžืขืชื™ืง ืืช ื”ื”ื’ื“ืจื•ืช ืฉื ืืกืคื• ืœืกืคืจื™ื™ื” ื ืคืจื“ืช ื•ืื– ืžืจื™ืฅ ืืช ื”ืกืงืจื™ืคื˜ ื•ืžืฉื ื” ืืช ื›ื•ืœื ื‘ื”ืžื•ื ื™ื”ื. ืœืื—ืจ ืžื›ืŸ, ื‘ื“ื™ืงื” ืืงืจืื™ืช - ื•ื ื™ืชืŸ ืœื”ืคื™ืฅ ืืช ื”ื”ื’ื“ืจื•ืช ื‘ื—ื–ืจื” ืœืžื›ื•ื ื•ืช.

ื”ืคืฆืช ืงื‘ืฆื™ pacs.xml ืฉื”ืฉืชื ื• ืœืœืงื•ื—ื•ืช

ื”ื“ื‘ืจ ื”ืคืฉื•ื˜ ื‘ื™ื•ืชืจ ืฉืขืœื” ื‘ืจืืฉ ื”ื™ื” ืœื‘ืฆืข ืฉื™ื ื•ื™ื™ื ื‘ืงื•ื‘ืฅ ื”-bat. ืฉื›ื‘ืจ ืขื•ื‘ื“ ืฉืื•ืกืฃ ืชืฆื•ืจื•ืช ืžืœืงื•ื—ื•ืช ื•ืœื”ื•ืกื™ืฃ ืืช ื”ืฉื•ืจื”:

If exist %APPDATA%RadiantViewerpacs.xml copy /Y srv.test.localpconfigsnew$pacs-%COMPUTERNAME%-%USERNAME%.xml %APPDATA%RadiantViewerpacs.xml

ืงื•ื‘ืฅ ื”-bat ื”ืกื•ืคื™ ื ืจืื” ื›ืš:

@echo off
If exist %APPDATA%RadiantViewerpacs.xml copy %APPDATA%RadiantViewerpacs.xml srv.test.localpconfigs$pacs-%COMPUTERNAME%-%USERNAME%.xml
If exist %APPDATA%RadiantViewerpacs.xml copy /Y srv.test.localpconfigsnew$pacs-%COMPUTERNAME%-%USERNAME%.xml %APPDATA%RadiantViewerpacs.xml

ืžืกืงื ื”

ื–ื” ื›ืžื• ื–ื” "ื”ื‘ืจืš"ืคืชืจื•ืŸ. ื ื™ืกื™ื ื• ืืช ื–ื” ื›ื‘ืจ ืคืขืžื™ื™ื (ื‘ืกืคื˜ืžื‘ืจ 2018 ื•ืคื‘ืจื•ืืจ 2019), ืขื“ ื›ื” ื”ื˜ื™ืกื” ืจื’ื™ืœื”. ื›ืžื•ื‘ืŸ, ืœื 100% ืžื”ืœืงื•ื—ื•ืช ืžืขื“ื›ื ื™ื, ืื‘ืœ ื–ื” ืงืจื•ื‘ ืœืขืจืš ื”ื–ื” - ืื ื—ื ื• ืžืฉืœื™ืžื™ื ืืช ื”ืฉืืจ ืžืจื—ื•ืง. ืชืกืจื™ื˜ ืžืืช ืงืฉืจ.

ืžืงื•ืจ: www.habr.com

ื”ื•ืกืคืช ืชื’ื•ื‘ื”