<?

class DromXMLGenerator
{
	protected $types = [];
	protected $dictionaries = [
		"car" => [], 
		"bus" => [], 
		"motorhome" => [], 
		"mobile_crane" => [], 
		"bulldozer" => [], 
		"atv" => [], 
		"truck" => [], 
		"building" => [], 
		"misc" => [], 
		"municipal" => [], 
		"forestry" => [], 
		"loader" => [], 
		"semi_trailer" => [], 
		"trailer" => [], 
		"truck_tractor" => [], 
		"tractor" => [], 
		"excavator" => [], 
	];
	protected $special_frames_mapping = [
		"BUS" => "bus", 
		"TRUCK" => "truck", 
		"TRUCK_TRACTOR" => "truck_tractor", 
		"MOTORHOME" => "motorhome", 
		"BUILDING" => "building", 
		"CRANE" => "mobile_crane", 
		"LOADER" => "loader", 
		"TRAILER" => "trailer", 
		"SEMITRAILER" => "semi_trailer", 
		"EXCAVATOR" => "excavator", 
		"FARM" => "tractor", 
		"MISC" => "misc", 
		"FORESTRY" => "forestry", 
		"MUNICIPAL" => "municipal", 
		"ATV" => "atv", 
		"BULLDOZER" => "bulldozer", 
		"QUADBIKE" => "atv", 
		"SNOWMOBILE" => "atv", 
		"SCOOTER" => "misc", 
	];
	protected $special_frames = [];

	protected $xml_cars = null;
	protected $xml_special = null;
	protected $offers_cars = null;
	protected $offers_special = null;
	protected $total = 0;
	protected $found_cars = 0;
	protected $found_special = 0;
	protected $valid_cars = 0;
	protected $valid_special = 0;
	protected $invalid_special = 0;
	protected $not_found_special = 0;
	protected $p1 = 0;
	protected $p2 = 0;
	protected $p3 = 0;
	protected $p4 = 0;

	protected $fuels = [
		"БЕНЗИН" => "GASOLINE", 
		"ГАЗ" => "GAS", 
		"ДИЗЕЛЬ" => "DIESEL", 
		"ЭЛЕКТРИЧЕСКИЙ" => "ELECTRICITY", 
	];

	protected $errors = "";

	function __construct()
	{
		$this->xml_cars = new SimpleXMLElement("<?xml version=\"1.0\" encoding=\"utf-8\" ?><avtoxml></avtoxml>");
		$this->offers_cars = $this->xml_cars->addChild('Offers');

		$this->xml_special = new SimpleXMLElement("<?xml version=\"1.0\" encoding=\"utf-8\" ?><avtoxml></avtoxml>");
		$this->offers_special = $this->xml_special->addChild('SpecOffers');

		$this->loadTypes();

		foreach($this->dictionaries AS $type => $v)
		{
			$structure = [
				"brands" => [], 
				"models" => [], 
				"cities" => [], 
				"bodies" => [], 
				"colors" => [], 
				"transmissions" => [], 
				"engines" => [], 
				"wheels" => [], 
				"fuels" => [], 
			];

			$url = "https://www.drom.ru/cached_files/autoload/files/";
			if($type === "car")
			{
				$url = $url."ref.xml";
			}
			else
			{
				$url = $url."ref_".$type.".xml";
			}

			$response_xml = file_get_contents($url);
			file_put_contents("/home/bitrix/www/local/ref_".$type.".xml", $response_xml);

			$structure_object = new SimpleXMLElement($response_xml);

			foreach($structure_object->MarksSpec->MarkSpec AS $mark)
			{
				$k = mb_strtoupper((string) $mark->sMarkSpec);
				$n = (int) $mark->idMarkSpec;

				$models = [];
				foreach($structure_object->ModelsSpec->ModelSpec AS $model)
				{
					$mmn = (int) $model->idMarkSpec;
					
					if($mmn === $n)
					{
						$km = mb_strtoupper((string) $model->sModelSpec);
						$nm = (int) $model->idModelSpec;

						$models[ $km ] = $nm;
						$structure['models'][ $km ] = $nm;
					}
				}

				$structure['brands'][ $k ] = [ "id" => $n, "models" => $models ];
			}

			foreach($structure_object->Marks->Mark AS $mark)
			{
				$k = mb_strtoupper((string) $mark->sMark);
				$n = (int) $mark->idMark;

				$models = [];
				foreach($structure_object->Models->Model AS $model)
				{
					$mmn = (int) $model->idMark;
					
					if($mmn === $n)
					{
						$km = mb_strtoupper((string) $model->sModel);
						$nm = (int) $model->idModel;

						$models[ $km ] = $nm;
					}
				}

				$structure['brands'][ $k ] = [ "id" => $n, "models" => $models ];
			}

			foreach($structure_object->Cities->City AS $city)
			{
				$k = mb_strtoupper((string) $city->sCity);
				$n = (int) $city->idCity;

				$structure['cities'][ $k ] = $n;
			}

			foreach($structure_object->FrameTypes->FrameType AS $frame_type)
			{
				$k = mb_strtoupper((string) $frame_type->sFrameType);
				$n = (int) $frame_type->idFrameType;

				$structure['bodies'][ $k ] = $n;
			}

			foreach($structure_object->Colors->Color AS $color)
			{
				$k = mb_strtoupper((string) $color->sColor);
				$n = (int) $color->idColor;

				$structure['colors'][ $k ] = $n;
			}

			foreach($structure_object->WheelFormulaTypes->WheelFormulaType AS $wheel_type)
			{
				$k = mb_strtoupper((string) $wheel_type->sWheelFormulaType);
				$n = (int) $wheel_type->idWheelFormulaType;

				$structure['wheels'][ $k ] = $n;
			}

			foreach($structure_object->EngineTypesSpec->EngineTypeSpec AS $engine_type)
			{
				$k = mb_strtoupper((string) $engine_type->sEngineTypeSpec);
				$n = (int) $engine_type->idEngineTypeSpec;

				$structure['fuels'][ $k ] = $n;
			}

			$this->dictionaries[ $type ] = $structure;
		}
	}

	function addOffer($entry)
	{
		$this->total++;

		$type = $entry['PROPERTIES']['VEHICLE_TYPE']['VALUE'];
		$subtype = $entry['PROPERTIES']['VEHICLE_SUBTYPE']['VALUE'];
		//print $type." ".$subtype."\n";

		if($type === "Лёгкий коммерческий")
		{
			$this->found_special++;
			$this->buildOffer(true, [ 'group' => 'truck', 'id' => 27 ], $entry);
		}
		else
		{
			if($subtype === "Легковой автомобиль")
			{
				$this->found_cars++;	
				$this->buildOffer(false, [ 'group' => 'car' ], $entry);

				/*
				$idMark = $this->getDictionaryRecordId($this->dictionaries['car']['brands'], mb_strtoupper($entry['PROPERTIES']['BRAND']['RELATED']['NAME']));
				//print $entry['CODE']." - ".$entry['PROPERTIES']['BRAND']['RELATED']['NAME']." - ".$entry['PROPERTIES']['MODEL']['RELATED']['NAME']." - [".$idMark."] - [".$idModel."]\n";
				//if(is_null($idMark)) { $this->errors .= "Не найдена марка ".$entry['PROPERTIES']['BRAND']['RELATED']['NAME']."\n"; continue; }

				if($idMark !== null)
				{
					//* id марки авто (см. файл-справочник); если не можете указать id, то укажите название марки текстом в поле sMark
					$offer['idMark'] = $idMark;
				}
				else
				{
					//* название марки авто (Toyota, Honda, BMW и т.п.); указывать обязательно только в том случае, если не можете указать idMark
					$offer['sMark'] = $entry['PROPERTIES']['BRAND']['RELATED']['NAME'];
				}

				$idModel = $this->getDictionaryRecordId($this->dictionaries['car']['models'], mb_strtoupper($entry['PROPERTIES']['MODEL']['RELATED']['NAME']));
				//if(is_null($idModel)) { $this->errors .= "Не найдена модель ".$entry['PROPERTIES']['MODEL']['RELATED']['NAME']." для ".".$entry['PROPERTIES']['BRAND']['RELATED']['NAME']."."\n"; continue; }
				if($idModel !== null)
				{
					//* id модели авто (см. файл-справочник); если не можете указать id, то укажите название модели текстом в поле sModel
					$offer['idModel'] = $idModel;
				}
				else
				{
					//* название модели авто (Land Cruiser, Accord, X5 и т.п.); указывать обязательно только в том случае, если не можете указать idModel
					$offer['sModel'] = $entry['PROPERTIES']['MODEL']['RELATED']['NAME'];
				}
				*/

				/*
				$payload = [
					"idOffer" => $entry['CODE'], //* уникальный id объявления в вашей базе данных
					"idMark" => "", //* id марки авто (см. файл-справочник); если не можете указать id, то укажите название марки текстом в поле sMark
					"idModel" => "", //* id модели авто (см. файл-справочник); если не можете указать id, то укажите название модели текстом в поле sModel
					"sMark" => "", //* название марки авто (Toyota, Honda, BMW и т.п.); указывать обязательно только в том случае, если не можете указать idMark
					"sModel" => "", //* название модели авто (Land Cruiser, Accord, X5 и т.п.); указывать обязательно только в том случае, если не можете указать idModel
					"idCountry" => "", //id страны, где находится авто (см. файл-справочник, по умолчанию — 0)
					"idCity" => "", //id города, в котором находится авто (см. файл-справочник)
					"sCity" => "", //название города, в котором находится авто (см. файл-справочник)
					"YearOfMade" => "", //год выпуска ТС (только год, 4 цифры: 1995, 2003, 2018 и т.п.)
					"VIN" => $entry['PROPERTIES']['VIN']['VALUE'], //* VIN или номер кузова, если VIN отсутствует
					"Price" => $entry['PROPERTIES']['PRICE']['VALUE'], //цена в рублях
					"NewType" => 0, //признак, что автомобиль новый; 1 — новый, 0 — не новый (с пробегом)
					"Volume" => $entry['PROPERTIES']['ENGINE_VOLUME']['VALUE'], //объем двигателя в куб.см (пример: 599, 1300, 2631 и т.п.)
					"FrameType" => "???", //тип кузова (см. файл-справочник)
					"Color" => "???", //цвет кузова (см. файл-справочник)
					"idTransmission" => "???", //id типа трансмиссии (см. файл-справочник)
					"sTransmission" => "???", //название типа трансмиссии
					"idEngineType" => "", //id типа двигателя (см. файл-справочник)
					"sEngineType" => "", //название типа двигателя
					"idHybridType" => "", //гибрид (см. файл-справочник)
					"sHybridType" => "", //гибрид (да, нет)
					"idGbo" => "", //ГБО (см. файл-справочник)
					"sGbo" => "", //ГБО (да, нет)
					"idDriveType" => "???", //id типа двигателя (см. файл-справочник)
					"sDriveType" => "", //название типа двигателя
					"sWheelType" => "", //положение руля (левый, правый)
					"Haul" => "", //пробег (показания одометра в километрах)
					"sComplectation" => "", //название комплектации (в соответствии с каталогом)
					"idComplectation" => "", //id комплектации на Дроме (в соответствии с каталогом)
					"Additional" => "", //текстовое описание ТС (комплектация, оснащение, тюнинг и т.п.), здесь можно указать сссылку на видео, размещенное на YouTube 
					"Photos" => "", //секция со списком фотографий (ниже есть подробное описание секции)
					"Phone" => "", //номер телефона (поле не должно быть больше 20 символов)
					"Whereabouts" => "", //авто в наличии или под заказ (см. файл-справочник)
					"Power" => $entry['PROPERTIES']['ENGINE_POWER']['VALUE'], //мощность автомобиля в лошадиных силах
					"idCertProgram" => "", //программа сертификации (см. файл-справочник)
					"DamagedType" => "", //признак для поврежденных автомобилей (0 - небитые, 1 - битые или не на ходу)
					"SOR" => "", //номер свидетельства о регистрации ТС для авто с пробегом (10 символов)
				];
				*/
			}
			else
			{
				$this->found_special++;
		
				$frame = $this->getFrameType(mb_strtoupper($subtype), mb_strtoupper($entry['PROPERTIES']['MODEL']['RELATED']['NAME']));

				if(!is_null($frame))
				{
					$this->buildOffer(true, $frame, $entry);
				}
				else
				{
					$this->invalid_special++;
					print $this->invalid_special." НЕ УДАЛОСЬ ОПРЕДЕЛИТЬ ТИП: ".mb_strtoupper($subtype)." \t\t[ ".$entry['CODE']." ][ ".$entry['PROPERTIES']['BRAND']['RELATED']['NAME']." ][ ".$entry['PROPERTIES']['MODEL']['RELATED']['NAME']." ]\n";

					//$this->not_found_special++;
				}
			}
		}
	}

	private function buildOffer($special = false, $frame, $entry)
	{
		//print $entry['CODE']." - ".$type."\n"; 

		$payload = [
			"idOffer" => $entry['CODE'], //* уникальный id объявления в вашей базе данных
			"YearOfMade" => $entry['PROPERTIES']['YEAR']['VALUE'], //год выпуска ТС (только год, 4 цифры: 1995, 2003, 2018 и т.п.)
			"VIN" => $entry['PROPERTIES']['VIN']['VALUE'], //* VIN или номер кузова, если VIN отсутствует
			"Price" => $entry['PROPERTIES']['PRICE']['VALUE'], //цена в рублях
			"NewType" => 0, //признак, что автомобиль новый; 1 — новый, 0 — не новый (с пробегом)
			"Volume" => $entry['PROPERTIES']['ENGINE_VOLUME']['VALUE'], //объем двигателя в куб.см (пример: 599, 1300, 2631 и т.п.)
			"Power" => $entry['PROPERTIES']['ENGINE_POWER']['VALUE'], //мощность автомобиля в лошадиных силах
		];

		if(!empty($entry['PROPERTIES']['MILEAGE']['VALUE']))
		{
			$payload["Haul"] = $entry['PROPERTIES']['MILEAGE']['VALUE'];
		}

		if(!empty($entry['PROPERTIES']['AFTER_ACCIDENT']['VALUE']))
		{
			$payload[ $special ? "idDamagedType" : "DamagedType" ] = $entry['PROPERTIES']['AFTER_ACCIDENT']['VALUE_XML_ID'] == "YES" ? 1 : 0;
		}

		if($special)
		{
			$payload['idFrameTypeSpec'] = $frame['id'];
			$payload['idWheelType'] = 2;

			if(in_array($frame['group'], [ "bus", "motorhome" ]))
			{
				$this->invalid_special++;
				print $this->invalid_special." НЕВОЗМОЖНО УКАЗААТЬ DriveTypeSpec: ".$entry['CODE']." ".$entry['PROPERTIES']['BRAND']['RELATED']['NAME']." ".$entry['PROPERTIES']['MODEL']['RELATED']['NAME']."\n";
				return;
			}

			if(in_array($frame['group'], [ "trailer", "semi_trailer" ]))
			{
				$this->invalid_special++;
				print $this->invalid_special." НЕВОЗМОЖНО УКААЗАТЬ КОЛИЧЕСТВО ОСЕЙ Axles: ".$entry['CODE']." ".$entry['PROPERTIES']['BRAND']['RELATED']['NAME']." ".$entry['PROPERTIES']['MODEL']['RELATED']['NAME']."\n";
				return;
			}

			if(in_array($frame['group'], [ "truck", "truck_tractor", "mobile_crane", "municipal", ]))
			{
				$item_name = str_replace("Х", "X", mb_strtoupper($entry['PROPERTIES']['MODEL']['RELATED']['NAME']));
				preg_match('/\dX\d/', $item_name, $wheel_type_matches);

				$idWheelFormulaType = $this->getDictionaryRecordId($this->dictionaries[ $frame['group'] ]['wheels'], $wheel_type_matches[0]);
				if(!is_null($idWheelFormulaType))
				{
					$payload['idWheelFormulaType'] = $idWheelFormulaType;
				}
				else
				{
					if(stripos($item_name, "КАБИНЕТ") !== false || stripos($item_name, "ФУРГОН") !== false || stripos($item_name, "БОРТОВОЙ") !== false || stripos($item_name, "СОБОЛЬ") !== false)
					{
						$payload['idWheelFormulaType'] = $this->getDictionaryRecordId($this->dictionaries[ $frame['group'] ]['wheels'], "4X2");
					}
					else
					{
						$this->invalid_special++;
						print $this->invalid_special." НЕТ КОЛЕСНОЙ ФОРМУЛЫ: ".$entry['CODE']." - ".$item_name." [".$wheel_type_matches[0]."]\n";
						return;
					}
				}
			}

			if(in_array($frame['group'], [ "bus", "truck", "truck_tractor", "mobile_crane", "loader", "municipal", "atv", "motorhome" ]))
			{
				if(!empty($entry['PROPERTIES']['ENGINE_FUEL']['VALUE']))
				{
					$f = mb_strtoupper($entry['PROPERTIES']['ENGINE_FUEL']['VALUE']);
					if(isset($this->fuels[$f]))
					{
						$idEngineTypeSpec = $this->getDictionaryRecordId($this->dictionaries[ $frame['group'] ]['fuels'], $this->fuels[$f]);

						if(!is_null($idEngineTypeSpec))
						{
							$payload['idEngineTypeSpec'] = $idEngineTypeSpec;
						}
					}
				}
			}
		}

		if($special)
		{
			$patterns = array('/\s\dX\d/i', '/\s\dХ\d/i', '/САМОСВАЛ/i');
			$replacements = array('', '', '');
			$model_name = preg_replace($patterns, $replacements, mb_strtoupper($entry['PROPERTIES']['MODEL']['RELATED']['NAME']));
			$model_name = ltrim(rtrim($model_name));

			$model_name_chunks = explode(" ", $model_name);
			array_unshift($model_name_chunks, implode('', $model_name_chunks));

			$idModel = null;
			foreach($model_name_chunks AS $c)
			{
				$idModel = $this->getDictionaryRecordId($this->dictionaries[ $frame['group'] ]['models'], $c);
				if(!is_null($idModel))
				{
					break;
				}
			}

			if(!is_null($idModel))
			{
				$payload['idModelSpec'] = $idModel;
			}
			else
			{
				$this->invalid_special++;
				print $this->invalid_special." НЕВОЗМОЖНО ОПРЕДЕЛИТЬ МОДЕЛЬ ДЛЯ МАРКИ ".$entry['PROPERTIES']['BRAND']['RELATED']['NAME'].": ".$entry['CODE']." - ".$entry['PROPERTIES']['MODEL']['RELATED']['NAME']."\n";

				return;
			}
		}
		else
		{
			$idMark = $this->findInDictionaryRecordId($this->dictionaries[ $frame['group'] ]['brands'], mb_strtoupper($entry['PROPERTIES']['BRAND']['RELATED']['NAME']));
			//print $type." - ".$frame['group']." - ".$idMark['id']."\n";
	
			if(!is_null($idMark))
			{
				if(!$special) { $payload['idMark'] = $idMark['id']; }
				$this->p1++;
	
				$patterns = array('/\s\dX\d/i', '/\s\dХ\d/i', '/САМОСВАЛ/i');
				$replacements = array('', '', '');
				$model_name = preg_replace($patterns, $replacements, mb_strtoupper($entry['PROPERTIES']['MODEL']['RELATED']['NAME']));
				$model_name = ltrim(rtrim($model_name));
	
				$model_name_chunks = explode(" ", $model_name);
				array_unshift($model_name_chunks, implode('', $model_name_chunks));
	
				$idModel = null;
				foreach($model_name_chunks AS $c)
				{
					$idModel = $this->getDictionaryRecordId($this->dictionaries[ $frame['group'] ]['brands'][ mb_strtoupper($entry['PROPERTIES']['BRAND']['RELATED']['NAME']) ]['models'], $c);
					if(!is_null($idModel))
					{
						$idModel = $this->findInDictionaryRecordId($this->dictionaries[ $frame['group'] ]['brands'][ mb_strtoupper($entry['PROPERTIES']['BRAND']['RELATED']['NAME']) ]['models'], mb_strtoupper($c));
						if(!is_null($idModel))
						{
							break;
						}
					}
				}
	
				if(!is_null($idModel))
				{
					$payload['idModel'] = $idModel;
				}
				else
				{
					$payload['sModel'] = $model_name;
				}
			}
			else
			{
				$this->p2++;
	
				if(!$special)
				{
					$payload['sMark'] = $entry['PROPERTIES']['BRAND']['RELATED']['NAME'];
					$payload['sModel'] = $entry['PROPERTIES']['MODEL']['RELATED']['NAME'];
				}
				else
				{
					$this->invalid_special++;
					print $this->invalid_special." НЕВОЗМОЖНО ОПРЕДЕЛИТЬ МАРКУ: ".$entry['CODE']." (ТИП ".$frame['group'].") - ".$entry['PROPERTIES']['BRAND']['RELATED']['NAME']." ".$entry['PROPERTIES']['MODEL']['RELATED']['NAME']."\n";
	
					return;
				}
	
				//print $entry['PROPERTIES']['BRAND']['RELATED']['NAME']."\n";
			}
		}

		$idCity = $this->getDictionaryRecordId($this->dictionaries[ $frame['group'] ]['cities'], mb_strtoupper($entry['PROPERTIES']['PARKING_CITY']['VALUE']));
		if($idCity !== null)
		{
			//* id города, в котором находится авто (см. файл-справочник)
			$payload['idCity'] = $idCity;
		}
		else
		{
			if(!$special)
			{
				//* название города, в котором находится авто (см. файл-справочник)
				$payload['sCity'] = $entry['PROPERTIES']['PARKING_CITY']['VALUE'];
			}
			else
			{
				$this->invalid_special++;

				print $this->invalid_special." НЕВОЗМОЖНО ОПРЕДЕЛИТЬ ГОРОД: ".$entry['CODE']." ".$entry['PROPERTIES']['BRAND']['RELATED']['NAME']." ".$entry['PROPERTIES']['MODEL']['RELATED']['NAME']."\n";
				return;
			}

			//if(is_empty($idModel)) { $this->errors .= "Не найдена модель ".$entry['PROPERTIES']['MODEL']['RELATED']['NAME']." для ".".$entry['PROPERTIES']['BRAND']['RELATED']['NAME']."."\n"; continue; }
		}

		//"idCountry" => "", //id страны, где находится авто (см. файл-справочник, по умолчанию — 0)
		//"idCity" => "", //id города, в котором находится авто (см. файл-справочник)
		//"sCity" => "", //название города, в котором находится авто (см. файл-справочник)

		if($special)
		{
			$this->valid_special++;
		}
		else
		{
			$this->valid_cars++;
		}

		$offer = $special ? $this->offers_special->addChild('SpecOffer') : $this->offers_cars->addChild('Offer');
		foreach($payload AS $k => $v)
		{
			$offer->addChild($k, $v);
		}

		$offer->addChild("Additional", "Артикул: ".$entry['CODE']."\n".htmlspecialchars(str_replace(["&nbsp;", "<br>", "<br/>"], [" ", "", ""], strip_tags($entry['DETAIL_TEXT']))));

		if(count($entry['PHOTOS_1080']) > 0)
		{
			$photos = $offer->addChild("Photos");
			$photos->addAttribute('PhotoMain', "https://".SITE_SERVER_NAME.$entry['PHOTOS_1080'][0]);

			foreach($entry['PHOTOS_1080'] AS $photo)
			{
				$photos->addChild("Photo", "https://".SITE_SERVER_NAME.$photo);
			}
		}

		//print $type." MATCH"."\n";
	}

	private function normalize_string($str)
	{
		return str_replace(["Ё", "C"], ["Е", "С"], $str);
	}

	private function getFrameType($type, $model)
	{
		if($type === "ПРИЦЕП") { $type = "ДРУГИЕ ПРИЦЕПЫ"; }
		if($type === "ТЯГАЧ") { $type = "СЕДЕЛЬНЫЙ ТЯГАЧ"; }

		if(isset($this->special_frames[ $type ]))
		{
			return $this->special_frames[ $type ];
		}
		else
		{
			$found = [];

			foreach($this->special_frames AS $k => $v)
			{
				if(strpos($this->normalize_string($model), $k) > -1)
				{
					$found[ strlen($k) ] = $this->special_frames[ $k ];
				}
			}

			if(count($found) > 0)
			{
				krsort($found);
//				print_r($found);

				foreach($found AS $f)
				{
					return $f;
				}
//				return $found[0];
			}
		}

		//print "[".$this->normalize_string(mb_strtoupper($k))."] <---\n";
		return null;
	}

	private function getDictionaryRecordId($branch, $name)
	{
		if(isset($branch[ $name ]))
		{
			return $branch[ $name ];
		}

		return null;
	}

	private function findInDictionaryRecordId($branch, $name)
	{
		foreach($branch AS $k => $v)
		{
			if(strpos($name, $k) > -1)
			{
				return $v;
			}
		}

		return null;
	}

	function save()
	{
		if($this->total > 0)
		{
			print "ИТОГО: валидно ".$this->valid_cars + $this->valid_special." из ".$this->total." - ".number_format(($this->valid_cars + $this->valid_special) / (($this->found_cars + $this->found_special) / 100), 2, ".")."%\n";

			if($this->found_cars > 0)
			{
				print "ЛКТ: валидно ".$this->valid_cars." из ".$this->found_cars." - ".number_format($this->valid_cars / ($this->found_cars / 100), 2, ".")."%\n";
			}
			if($this->found_special > 0)
			{
				print "СПЕЦТЕХНИКА: валидно ".$this->valid_special." из ".$this->found_special." - ".number_format($this->valid_special / ($this->found_special / 100), 2, ".")."%\n";
			}

			file_put_contents("/home/bitrix/www/drom-offers.xml", $this->xml_cars->asXML());
			file_put_contents("/home/bitrix/www/drom-offers-special.xml", $this->xml_special->asXML());
		}
	}

	private function loadTypes()
	{
		$types_url = "https://www.drom.ru/cached_files/autoload/files/ref_frame_types.xml";
		$response_types_xml = file_get_contents($types_url);
		file_put_contents("/home/bitrix/www/local/ref_frame_types.xml", $response_types_xml);

		$types_object = new SimpleXMLElement($response_types_xml);
		foreach($types_object AS $group => $branch)
		{
			foreach($branch AS $spec)
			{
				$g = (string) $group;
				$k = (string) $spec->sFrameTypeSpec;
				$n = (int) $spec->idFrameTypeSpec;

				//print $g." - ".$k."\n";
				$this->special_frames[ mb_strtoupper($k) ] = [
					"group" => $this->special_frames_mapping[ $g ], 
					"id" => $n, 
				];
			}
		}
	}
}