<?

class store_words {
	private $data;

	private $statement;

	public function __construct() {

		$this->data = $data->main_instance;/*$data->fetch('main');*/

		$this->statement =  $data->statement;/*new statement();*/
	}

	public function store($tags) {
		foreach($tags as $tag_value => $vector) {
			/*$object->log('store');
			$object->log($tag_value);
			$object->log($object->toJSON($vector));*/
			$query = 'UPDATE tag_vectors SET vector_value = ?, rd7 = 150 WHERE tag_value = ?';
			$this->data->execute($query, [$object->toJSON($vector), $tag_value]);
		}
	}
}

class importer {

	public function __construct($path) {
		$text = $files->read_file($path);
		$lines = $object->strings->split_by($text);

		$object->log($lines->length);

		$data_instance = $data->main_instance;

		foreach($lines as $line) {

			$v = [
				'word' => $line
			];


			$insert = $data->statement->generate($v, 'prepositions');
			$data_instance->_($insert, $v);
		}
	}

}

class wordnet {

	public $vectors_by_type;

	public $data;

	public $evaluation;

	public $tags_vectors_index = [];

	public $statement;

	public $ignore_vector_columns;

	public $errors;

	public $main_types = NULL;

	public function get_all_children($id, $res) {
		$query = 'SELECT * FROM mediaitems WHERE parent_id = ?';
		$rows = $this->data->get_rows($query, [$id]);

		foreach($rows as $row) {
			$res[] = $row['id'];

			$this->get_all_children($row['id'], $res);
		}
	}

	public function populate_tag_vectors() {
		$set_values = $object->create();

		$moodtags = [
			['id' => 'Dark'],
			['id' => 'Powerful'],
			['id' => 'Raw'],
			['id' => 'Prototypical'],
			['id' => 'Feel Good'],
			['id' => 'Mellow'],
			['id' => 'Groove']
		];

		$set_values['moodtags'] = $moodtags;

		$query = 'SELECT id FROM albums';
		$albums = $this->data->get_rows($query, []);

		$object->log('albums is');

		$object->log($albums);

		$set_values['albums'] = $albums;

		$query = 'SELECT id FROM collections';
		$collections = $this->data->get_rows($query, []);


		$set_values['collections'] = $collections;

		$query = 'SELECT id FROM persons';
		$persons = $this->data->get_rows($query, []);
		$set_values['persons'] = $persons;

		$query = 'SELECT id FROM playlists';
		$playlists = $this->data->get_rows($query, []);
		$set_values['playlists'] = $playlists;

		$query = 'SELECT id FROM locations';
		$locations = $this->data->get_rows($query, []);
		$set_values['locations'] = $locations;

		foreach($set_values as $key => $items) {
			$object->log('key: '.$key);
			$object->log($items);
			$object->log($items->length);
				$object->log($object->toJSON($items));
			foreach($items as $item) {
				$object->log($object->toJSON($item));
				$tag_vector = [];

				while($tag_vector->length < 15) {
					$tag_vector[] = ($math->random_int(999) / 1000) - (1/2);
				}

				$v = [
					'tag_value' => $item['id'].'-'.$key,
					'fixedposition' => 0,
					'tag_vector' => $object->toJSON($tag_vector),
					'type' => $key
				];

				$query = 'SELECT * FROM tag_vectors WHERE tag_value = ? AND type = ?';
				$exists = $this->data->get_row($query, [$v['tag_value'], $v['type']]);

				if($exists == NULL) {


					$query = 'INSERT INTO tag_vectors (id, tag_value, fixedposition, vector_value, type) VALUES(?, ?, ?, ?, ?)';
					/*$vector = $this->vector->normalize_vector($vector);*/
					$values_query = [$data->main_instance->generate_uuid(), $v['tag_value'], $v['fixedposition'], $v['tag_vector'], $v['type']];
					$this->data->execute($query, $values_query);

					$object->log('set : '.$item['id']);

					$object->log($object->toJSON($tag_vector));

				}
			}
		}
	}

	/*public function fix_ids() {
		$tables = [
			'albums',
			'collections',
			'persons',

		];

		foreach($tables as $table) {
			$query = 'SELECT id FROM '.$table;
			foreach($this->data->get_rows($query, []) as $row) {
				$id = $row['id'];

				$query = 'UPDATE '.$table.' SET id = ? WHERE id = ?';
				$this->data->execute($query, [$id.'-'.$table, $id]);
			}
		}
	}*/

	public function __construct($skip=false) {

		$this->main_types =  [
			'nouns',
			'adjectives',
			'prepositions',
			'verbs',
			'adverbs'
		];
		$this->ignore_vector_columns = $object->create();
		$this->errors = $object->create();
		/*$evaluation = new evaluation();
		$evaluation->__set_configuration(16, NULL, ['value' => '0', 'remainder' => '1/10000'], false, 4, 4, true);

		$this->evaluation = $evaluation;*/

		$this->vector = new m_vector();

		$this->data = $data->main_instance;/*$data->fetch('main');*/

		$this->statement = $data->statement;/*new statement();*/

		$this->vectors_by_type = [
			'collections' => $object->create(),
			'persons' => $object->create(),
			'locations' => $object->create(), 
			'albums' => $object->create(),
			'tracks' => $object->create(),
			'playlists' => $object->create(),
			'moodtags' => $object->create()
		];



		/*$this->populate_tag_vectors();*/

		/*themes
tropes
format
genres
lists
persons
popculture
movies
companies*/
		/*
			-format & themes 2
			-genres 1
			-format + themes + genres með mesta vaegið. þannig t.d. ef það hefur allt somu tags.
			-lists 0.75
			-tropes 0.65
			-relations / allt sama vaegid.
			-popculture 0.3

			-persons med minnsta vaegid
			-artalid 
			-company

			hafa artalid sem dalk i toflunni sem breytist svo i dimension i vectornum sem denormalized gildi vid hvert skipti sem er sott ur databasinum.

			-saekja nyjustu gogn ur gagnagrunninum

			-prufa fyrst ad traina db-inn sem eg hef nuna med tilliti til alls vectorsins semsagt ignora set_index i length_value fallinu.
		*/

		$this->tags_vectors_index = $object->create();

		/*$query = 'SELECT COUNT(*) as count FROM tag_vectors';
		$object->log('get count');

		$count = $this->data_instance->get_row($query, [])['count'];

		$object->log($count);*/

		$query = 'SELECT * FROM tag_vectors';
		$tag_vectors = $this->data->get_rows($query, []);


		$object->log('completed');

		$object->log($this->tags_vectors_index);

		foreach($tag_vectors as $tag_vector_row) {
			$object->log($tag_vector_row);
			$object->log($object->toJSON($tag_vector_row));
			$object->log($tag_vector_row['tag_value']);
			$this->tags_vectors_index[$tag_vector_row['tag_value']] = [
				'vector_value' => $object->fromJSON($tag_vector_row['vector_value']),
				'type' => $tag_vector_row['type'],
				'connections' => $object->create()
			];
			$object->log($object->toJSON($object->keys($this->tags_vectors_index)));

		}

		$object->log($this->tags_vectors_index);
		/*$query = 'SELECT * FROM tracks';
		$rows = $this->data->get_rows($query, []);

		$is_child_index = $object->create();

		$by_id_index = $object->create();*/

		/*foreach($rows as $row) {
			$object->log('get children');
			$all_children = [];
			$this->get_all_children($row['id'], $all_children);

			foreach($all_children as $child) {
				$is_child_index[$child] = true;
			}

			$row['children'] = $all_children;

			$by_id_index[$row['id']] = $row;
		}*/

		/*$acceptible_tags = $object->create();*/

		$object->log('completed');

		$object->log($this->tags_vectors_index);

		$object->log($object->keys($this->tags_vectors_index));
		$object->log($object->toJSON($object->keys($this->tags_vectors_index)));

		foreach($this->tags_vectors_index as $tag_value => $tag_item_main) {
			$object->log($tag_value);
			$object->log($tag_item_main);
			$all_tags = [];
			$object->log('type : '.$tag_item_main['type']);

			$tag_value_without = $tag_value;
			$split = $object->strings->split($tag_value, '-');
			$split = $object->reverse($split);
			$object->splice($split, 0, 1);
			$split = $object->reverse($split);

			$tag_value_without = $object->strings->join($split, '-');

			if($tag_item_main['type'] == 'persons') {

				$query = 'SELECT * FROM persons WHERE id = ?';
				$row = $this->data->get_row($query, [$tag_value_without]);

				$object->log($row);

				if($row != NULL) {
					$all_tags = [$row['locations_id'].'-locations', $row['collections_id'].'-collections'];
					/*if($row['persons_id'] != NULL) {
						$all_tags[] = $row['persons_id'];
					}*/

					$object->log($object->toJSON($row));
				}


			} else if($tag_item_main['type'] == 'tracks') {
				$query = 'SELECT * FROM tracks WHERE id = ?';
				$row = $this->data->get_row($query, [$tag_value_without]);

				$all_tags = [$row['albums_id'].'-albums', $row['collections_id'].'-collections'];

				if($row['moodtags'] != NULL && $object->strings->strlen($row['moodtags']) > 0) {
					$moodtags = $object->fromJSON($row['moodtags']);

					foreach($moodtags as $moodtag) {
						$all_tags[] = $moodtag.'-moodtags';
					}

					/*
						find commonalities in lyrics
					*/
				}

				$query = 'SELECT * FROM tracks_persons WHERE tracks_id = ?';
				$persons = $this->data->get_rows($query, [$row['id']]);

				foreach($persons as $person) {
					$all_tags[] = $person['persons_id'].'-persons';
				}

				/*foreach($all_tags as $tag) {
					$tag_item = $this->tag_vectors_index[$tag];

					if(!$object->isset($tag_item['tracks'])) {
						$tag_item['tracks'] = [];
					}

					($tag_item['tracks'])[] = $tag_item_main;

					$type = $tag_item['type'];

					if(!$object->isset($tag_item_main[$type])) {
						$tag_item_main[$type] = [];
					}
					($tag_item_main[$type])[] = $tag_item;
				}*/

			}



			foreach($all_tags as $tag) {
				$tag_item = $this->tags_vectors_index[$tag];

				if($object->isset($tag_item) && $tag_item != NULL && $tag_item != 0 && $tag_item_main != 0 && $tag_item_main != NULL && $object->isset($tag_item_main)) {

					if(!$object->isset($tag_item['connections'][$tag_item_main['type']])) {
						$tag_item['connections'][$tag_item_main['type']] = [];
					}

					$set_append_item = $tag_item['connections'][$tag_item_main['type']];
					$set_append_item[] = $tag_item_main;

					$type = $tag_item['type'];

					if(!$object->isset($tag_item_main['connections'][$type])) {
						$tag_item_main['connections'][$type] = [];
					}
					$append_item = $tag_item_main['connections'][$type];
					$append_item[] = $tag_item;
				}
			}
		}

	}

	public function run_vault() {
		$counter = 0;

		$vectors = [];
		$self = $this;


		foreach($this->tags_vectors_index as $tag_value => $tag_item_main) {
			$vectors[] = $tag_item_main['vector_value'];
		}

		$iteration_count = 0;


		$completed = function() {
			/*$self->run_test('282-albums');
			$self->run_test('140-albums');*/
			$self->run_test('226-albums');

			$object->log('after train');

			$this->denormalize($vectors);
			$object->log('denormalized');
			$this->store();
			$object->log('stored');
		};


		$started = [];

		$tags_vectors_index = $this->tags_vectors_index;


		$key_len = $object->keys($tags_vectors_index)->length;
		$object->log('key len: '.$key_len);

		$set_completed = NULL;


		$partitions = $object->partition_assoc($tags_vectors_index, 3);

		/*$partitions = [$tags_vectors_index];*/

		$wrap = async function($tag_item_main) {
			$self->train_sub_item($tag_item_main);
			$started[] = true;
			if($started->length == $key_len) {
				$object->once($set_completed);
			}
		};


		$start = function() {


			$set_completed = function() {

				$iteration_count = $iteration_count + 1;
				$object->log('iteration : '.$iteration_count);
				if($iteration_count < 500) {
					$started = [];
					$this->store();
					$object->dispatch($start);
				} else {
					$object->once($completed);
				}
			};

				/*$object->partitions_main = $partitions;
			}*/

			$partition_callback = async function($partition_value) {

				/*foreach($partition_value as $title => $movie) {
					$object->log('in title: '.$title);
					$wrap_item($title, $movie);
				}*/
				foreach($partition_value as $tag_value => $tag_item_main) {

					$wrap($tag_item_main);
				}

			};

			foreach($partitions as $partition_item) {
				$partition_callback($partition_item);
			}		
			/*foreach($tags_vectors_index as $tag_value => $tag_item_main) {

				$wrap($tag_item_main);
			}*/
			$counter = $counter + 1;
			$object->log('after train: '.$counter);

			/*if($math->mod($counter, 150) == 0) {
				$this->denormalize($vectors);
			}*/

		};

		$start();
	}

	public function __construct_depr($skip=false) {

		$this->main_types =  [
			'nouns',
			'adjectives',
			'prepositions',
			'verbs',
			'adverbs'
		];
		$this->ignore_vector_columns = $object->create();
		$this->errors = $object->create();
		/*$evaluation = new evaluation();
		$evaluation->__set_configuration(16, NULL, ['value' => '0', 'remainder' => '1/10000'], false, 4, 4, true);

		$this->evaluation = $evaluation;*/

		$this->vector = new m_vector();

		$this->data = $data->main_instance;/*$data->fetch('main');*/

		$this->statement = $data->statement;/*new statement();*/

		$this->vectors_by_type = [
			'collections' => $object->create(),
			'persons' => $object->create(),
			'locations' => $object->create(), 
			'albums' => $object->create(),
			'tracks' => $object->create(),
			'playlists' => $object->create(),
			'moodtags' => $object->create()
		];



		$this->populate_tag_vectors();

		/*themes
tropes
format
genres
lists
persons
popculture
movies
companies*/
		/*
			-format & themes 2
			-genres 1
			-format + themes + genres með mesta vaegið. þannig t.d. ef það hefur allt somu tags.
			-lists 0.75
			-tropes 0.65
			-relations / allt sama vaegid.
			-popculture 0.3

			-persons med minnsta vaegid
			-artalid 
			-company

			hafa artalid sem dalk i toflunni sem breytist svo i dimension i vectornum sem denormalized gildi vid hvert skipti sem er sott ur databasinum.

			-saekja nyjustu gogn ur gagnagrunninum

			-prufa fyrst ad traina db-inn sem eg hef nuna med tilliti til alls vectorsins semsagt ignora set_index i length_value fallinu.
		*/

		$this->tags_vectors_index = $object->create();

		/*$query = 'SELECT COUNT(*) as count FROM tag_vectors';
		$object->log('get count');

		$count = $this->data_instance->get_row($query, [])['count'];

		$object->log($count);*/
		$query = 'SELECT * FROM tracks';
		$rows = $this->data->get_rows($query, []);

		$is_child_index = $object->create();

		$by_id_index = $object->create();

		/*foreach($rows as $row) {
			$object->log('get children');
			$all_children = [];
			$this->get_all_children($row['id'], $all_children);

			foreach($all_children as $child) {
				$is_child_index[$child] = true;
			}

			$row['children'] = $all_children;

			$by_id_index[$row['id']] = $row;
		}*/

		/*$acceptible_tags = $object->create();*/

		foreach($rows as $row) {
			if(!$object->isset($is_child_index[$row['id']])) {
				/*$all_tags = [];
				if($row['all_cache_field_search'] != NULL && $object->strings->strlen($row['all_cache_field_search']) > 0) {
					$all_tags = $object->fromJSON($row['all_cache_field_search']);

					if($row['children']->length > 0) {
						foreach($row['children'] as $child_id) {
							if($object->isset($by_id_index[$child_id])) {
								$child = $by_id_index[$child_id];
								if($child['all_cache_field_search'] != NULL && $object->strings->strlen($child['all_cache_field_search']) > 0) {
									$append_tags = $object->fromJSON($child['all_cache_field_search']);

									$all_tags = $object->concat($all_tags, $append_tags);
								}
							}
						}
					}
				}
				if(!$object->isset($all_tags) || $all_tags == NULL) {
					$all_tags = [];
				}
				$all_tags = $object->array_unique($all_tags);

				$query = 'SELECT * FROM mediaitemslists, lists WHERE mediaitems_id = ? AND lists.id = lists_id';
				$lists = $this->data->get_rows($query, [$row['id']]);

				$lists = $object->map($lists, function($e) {
					return $e['value'];
				});

				$query = 'SELECT format FROM mediaitems WHERE id = ?';
				$mediaitem = $this->data->get_row($query, [$row['id']]);

				if($mediaitem != NULL) {
					if($mediaitem['format'] != NULL && $mediaitem['format'] != '') {
						$all_tags[] = $mediaitem['format'];
					}
				}

				$all_tags = $object->concat($lists, $all_tags);

				if($all_tags->length > 3) {*/
					$all_tags = [$row['albums_id'], $row['collections_id']];

					if($row['moodtags'] != NULL && $object->strings->strlen($row['moodtags']) > 0) {
						$moodtags = $object->fromJSON($row['moodtags']);

						foreach($moodtags as $moodtag) {
							$all_tags[] = $moodtag;
						}

						/*
							find commonalities in lyrics
						*/
					}

					$query = 'SELECT * FROM tracks_persons WHERE tracks_id = ?';
					$persons = $this->data->get_rows($query, [$row['id']]);

					foreach($persons as $person) {
						$all_tags[] = $person['persons_id'];
					}

					/*$query = 'SELECT * FROM albums WHERE id = ?';
					$album_row = $this->sql->get_row($query, [$row['albums_id']]);

					if($album_row != NULL) {
						$all_tags[] = $album_row['id'];


						$query = 'SELECT * FROM collections WHERE id = ?';
						$collection_row = $this->sql->get_row($query, [$album_row['collections_id']]);

						if($collection_row != NULL) {
							$all_tags[] = $collection_row['id'];
						}
					}*/


					$item = [
						'vector_value' => NULL,
						'all_tags' => $all_tags,
						'tag_value' => $row['id'],
						'year' => $row['year']
					];

					/*foreach($all_tags as $acceptible_tag) {
						$acceptible_tags[$acceptible_tag] = true;
					}*/
					/*$acceptible_tags['SUPER_'] = true;*/

					$this->vectors_by_type['movies'][$row['id']] = $item;
				/*}*/
			}
		}
		/* WHERE type != ? and type != ? and type != ? and type != ? and type != ?*/
		$query = 'SELECT * FROM tag_vectors'; /* ORDER BY RANDOM() LIMIT 100';*/
		$rows = $this->data->get_rows($query, []); /*$this->main_types*/



		$this->tag_type_index = $object->create();

		foreach($rows as $row) {

			/*$object->log($row['tag_value']);
			$object->log($row['type']);*/
			/*$object->log($object->toJSON(['title' => $row['tag_value'], 'type' => $row['type']]));*/
			if($object->isset($row['tag_value']) && $row['tag_value'] != NULL/* && $object->index_of($this->main_types, $row['type']) == (-1)*/) {
				if(true || ($object->isset($acceptible_tags[$row['tag_value']]) || $row['type'] == 'movies')) {
					$this->tag_type_index[$row['tag_value']] = $row['type'];
					/*if($row['type'] != 'format') {*/


	/*id|tag_value|scalar_value|tag_vectors_id|locked|complexity_simplicity|intensity|seriousness|comedicity|absurdity|physicality|violence|romance|surprisinginess_predictability|scale|locality_globality|structure_randomness|intellectuality_mindlessness|rd1|rd2|rd3|rd4|rd5|rd6|rd7|complexity_simplicity_locked|intensity_locked|seriouesness_locked|comedicity_locked|absurdity_locked|physicality_locked|violence_locked|action_locked|romance_locked|surprisingness_predictability_locked|scale_locked|locality_globality_locked|stucture_randomness_locked|intellectuality_mindlessness_locked|action_value|type*/

						/*$vector_value = [
							$row['intensity'],
							$row['seriousness'],
							$row['comedicity'],
							$row['absurdity'],
							$row['physicality'],
							$row['violence'],
							$row['action_value'],
							$row['romance'],
							$row['surprisinginess_predictability'],
							$row['scale'],
							$row['locality_globality'],
							$row['structure_randomness'],
							$row['intellectuality_mindlessness'],
							$row['rd1'],
							$row['rd2'],
							$row['rd3'],
							$row['rd4'],
							$row['rd5'],
							$row['rd6'],
							$row['rd7']
						];*/
						/*$object->log($row['tag_value']);
						$object->log($row['vector_value']);*/
						$vector_value = $object->fromJSON($row['vector_value']);




						$this->tags_vectors_index[$row['tag_value']] = $vector_value;
						/*foreach($vector_value as $index => $value_vector) {
							$vector_value[$index] = $evaluation->whole_common($value_vector);
						}*/
						/*$object->log('set vector '.$row['tag_value']);
						$object->log($object->toJSON($row));
						$object->log($object->toJSON($vector_value));*/
						if($row['type'] == 'tracks') {
							if($object->isset($this->vectors_by_type['movies'][$row['tag_value']])) {
								$this->vectors_by_type['movies'][$row['tag_value']]['fixedposition'] = $row['fixedposition'];
								$this->vectors_by_type['movies'][$row['tag_value']]['vector_value'] = $vector_value;
								/*$vector_value[6] = 1;*/ /*$this->vectors_by_type['movies'][$row['tag_value']]['year'];*/
							}
						} else if($row['type'] != 'tracks') {
							$item = [
								'vector_value' => $vector_value,
								'tag_value' => $row['tag_value'],
								'fixedposition' => $row['fixedposition']/*,
								'years' => 0*/
							];


							$this->vectors_by_type[$row['type']][$row['tag_value']] = $item;
						}
					/*}*/
				}
			}
		}

		$object->log('ended: ');

		foreach($this->vectors_by_type as $type => $values) {
			$object->log('type');
			$object->log($type);
			$object->log($object->keys($values)->length);
			$object->log($object->values($values)->length);
			if($type == 'tracks') {
				/*$object->log('movies');
				foreach($values as $tag => $vector) {
					$object->log($tag);
					$object->log($object->toJSON($vector));
				}
				$object->log('movies-end');*/
				$delete_index = [];
				foreach($values as $movie => $item) {
					if($item['vector_value'] === NULL) {
						$delete_index[] = $movie;
						/*$object->log($item['vector_value']);
						$object->log('delete: '.$movie);*/
					}
				}

				foreach($delete_index as $index_value) {
					delete $values[$index_value];
				}
			}

			$object->log($object->keys($values)->length);
			$object->log($object->values($values)->length);
		}

		foreach($this->vectors_by_type['movies'] as $movie_title => $item) {
			/*$object->log($movie_title);*/
			/*$object->log($object->toJSON($item));*/
			$tags = $item['all_tags'];
			/*$object->log($tags);
			$object->log($object->toJSON($tags));*/
			foreach($tags as $tag_value) {
				if($tag_value != NULL && $object->strings->strlen($tag_value) > 0) {

					$tag_value = $object->strings->trim($tag_value);
					/*$object->log($tag_value.'-'.$object->strings->strlen($tag_value));*/
					if($object->isset($this->tag_type_index[$tag_value])) {
						/*$object->log('get tag type index');*/
						$type = $this->tag_type_index[$tag_value];
						/*$object->log($type);*/
						if($object->isset($type)/* && $type != 'persons'*/) { /* && $type != 'persons'*/
							$associated_tag_item = $this->vectors_by_type[$type][$tag_value];
							/*$object->log($associated_tag_item);*/
							if($object->isset($associated_tag_item)) {
								if(!$object->isset($item[$type])) {
									$item[$type] = $object->create();
								}
								if(!$object->isset($item['tags_vectors'])) {
									$item['tags_vectors'] = $object->create();
								}

								$item[$type][$tag_value] = $associated_tag_item;
								$item['tags_vectors'][$tag_value] = $associated_tag_item;

								if(!$object->isset($associated_tag_item['movies'])) {
									$associated_tag_item['movies'] = $object->create();
								}
								$associated_tag_item['movies'][$movie_title] = $item;

								/*$associated_tag_item['years'] += $item['year'];*/
							}
						}
					}
				}
			}
		}


		/*foreach($this->vectors_by_type as $type => $values) {
			foreach($values as $item) {*/
				/*if($object->isset($item['years']) && $object->isset($item['movies'])) {
					$item['years'] = $item['years'] / $item['movies']->length;

					$object->log('years: ');
					$object->log($item['years']);
				}*/

				/*$object->log($object->toJSON($item));*/

/*				if($object->isset($item['movies'])) {
					$item['vector_value'][6] = 1;*/

					/*foreach($item['movies'] as $movie) {
						$item['vector_value'][6] += $movie['year'];
					}
					$item['vector_value'][6] = $item['vector_value'][6] / $item['movies']->length;*/

					/*$object->log('years: ');
					$object->log($item['vector_value'][6]);*/
				/*}*/
			/*}
		}*/


		/*$this->denormalize($this->tags_vectors_index);*/

		$object->log('before train');

		$object->log('after train');



		/*$counter_training = 0;
		while($counter_training < 40) {*/
			/*1000*/
			/*$counter_training++;
		}*/
		/*$this->column_errors();*/
	}

	public $wordspace;

	public function run_test($tag_input) {
		$test = $this->tags_vectors_index[$tag_input]['vector_value'];
		if($this->current_index != (-1)) {
			$test = [...$test];
			$test = $object->splice($test, $this->current_index, 1);
		}
		/*$test = $this->vector->normalize($test);*/

		/*$super = $this->tags_vectors_index['SUPER_'];
		$super = $this->vector->normalize($super);
		$test = $this->vector->multiply_vector($test, $super);*/
		/*
			Ef test vectorinn er normalizadur tharf ad normaliza alla vectora sem eru bornir saman vid
			serstaklega ef thad er gert summa?
		*/
/*[0.520321311601464,0.48425310243185982,0.49849630786131305,0.49625207835390456];*/

		$object->log($tag_input);

		$object->log($object->toJSON($test));


		/*$test = $this->tags_vectors_index['Scream'];

		$object->log($object->toJSON($test));


		$test = $this->vector->add_vector($this->tags_vectors_index['Scream'], $this->tags_vectors_index['Comedy']);*/

		/*$test = $this->vector->add_vector($this->tags_vectors_index['Scream'], $this->tags_vectors_index['Comedy']);*/

		/*$test = $this->vector->normalize_vector($test);*/

		$min_value = -1;
		$min_tag = NULL;

		$min_tags = [];

		$distances = [];

		/*foreach($this->tags_vectors_index as $tag => $vector) {*/
		foreach($this->tags_vectors_index as $tag => $vector_item) {
			$vector = $vector_item['vector_value'];

			if($this->current_index != (-1)) {
				$vector = [...$vector];
				$vector = $object->splice($vector, $this->current_index, 1);
			}
			/*$vector = $this->vector->normalize($vector);*/
			/*$object->log($vector);
			$object->log($object->toJSON($vector));*/
		/*foreach($this->vectors_by_type['movies'] as $tag => $vector) {*/

			/*$vector = $this->vector->multiply_vector($vector, $super);*/

			$distance = $this->vector->length_value($test, $vector);
			/*$distance = $this->vector->length_value($test, $vector['vector_value']);*/
			/*$object->log($tag);
			$object->log($distance);*/
			/*if($distance < (10/100)) {
				$min_tags[] = $tag;
			}*/
			$distances[] = [
				'distance' => $distance,
				'tag' => $tag
			];
			/*if($min_value == (-1) || $distance < $min_value) {
				$min_value = $distance;
				$min_tag = $tag;

				$object->log('set min: '.$min_tag);
			}*/
		}

		$object->sort($distances, function($a, $b) {
			if($a['distance'] > $b['distance']) {
				return (-1);
			}
			if($a['distance'] == $b['distance']) {
				return 0;
			}
			return 1;
		});

		$min_tags = $distances;

		if($distances->length > 25) {
			$min_tags = $object->splice($distances, 0, 25);
		}

		/*$object->log('min tag: '.$min_tag);
		$object->log('min tag length: '.($min_tags->length));*/
		foreach($min_tags as $min_tag) {
			$object->log($object->toJSON([$min_tag]));

		}

		$object->log($object->toJSON($test));
	}

	public function run_words() {
		$send_vectors = [];

		$types = [
			'genres',
			'tropes',
			'popculture',
			'themes',
			'lists'
		];

		foreach($types as $type) {
			$vectors_by_type = $this->vectors_by_type[$type];

			foreach($vectors_by_type as $tag_name => $item) {
				$send_vectors[$tag_name] = $item['vector_value'];
				$object->log($object->toJSON(['tag_name' => $tag_name, 'item' => $item['vector_value']]));
			}
		}


		$this->wordspace = new wordspace();
		$object->wordspace = $this->wordspace;
		$this->wordspace->begin_batch_processing($send_vectors);


		$this->run();

	}

	public function run() {

		$counter_iteration = 0;

		/*$this->denormalize($this->tags_vectors_index);*/

		/*$this->store($this->tags_vectors_index);*/

		/*while($counter_iteration < 1) {*/
			/*$this->median_values = $object->create();*/

		/*$arr = [
			[4, 3, 1, 4, 3, 1, 6],
			[5, 3, 2, 4, 3, 7, 76],
			[0, 0, 1, 2, 2, 1, 1],
			[15, 16, 13, 12, 12, 11, 11]
		];

		$this->denormalize($arr);

		$object->log($object->toJSON($arr));	*/

		/*foreach($this->tags_vectors_index as $v) {
			$sum = 0;
			foreach($v as $index => $value) {
				$sum += $v[$index];
			}
			foreach($v as $index => $value) {
				$v[$index] = 0;
			}
			$v[0] = $sum;
		}*/
/*
		foreach($this->tags_vectors_index as $v) {
			foreach($v as $index => $value) {
				$v[$index] = $math->random_int(990)+10 / 1000;
			}
		}

*/
	/*	*/

			/*while($counter < 15) {

				$v[$counter] = $math->random_int(990)+10 / 1000;
				$counter++;
			}*/

			/*$v_normalized = $this->vector->normalize($v);

			foreach($v as $index => $value) {
				$v[$index] = $v_normalized[$index];
			}*/

		/*foreach($this->tags_vectors_index as $v) {
			foreach($v as $index => $value) {
				$v[$index] = $math->random_int(990)+10 / 1000;
			}
			while($v->length < 15) {
				$v[] = $math->random_int(990)+10 / 1000;
			}
		}

		$object->log('denomtralize');

		$this->denormalize($this->tags_vectors_index);
		$this->store($this->tags_vectors_index);

		$object->log('stored');*/


		/*$vectors = [$vector_a, $vector_b, $vector_c];*/

		/*$vectors = [[2/10, 12/10, 2], [20, 1/3, 1/5], [10, 123, 135], [201, 12/3, 15/5], [20/25, 12/3, 25/5]];*/

	/*	$object->log($object->toJSON($vectors));

		$this->denormalize($vectors);
		$object->log($object->toJSON($vectors));
	*/

		/*$vectors = [[...$vector_a], [...$vector_b]];

		foreach($vectors as $v) {

			$this->denormalize_vertically($v);
			$object->log($object->toJSON($v));
		}*/

/*		$this->run_test('Die Hard');*/



		/*$this->run_test('Rush Hour');
		$this->run_test('Scream');
		$this->run_test('Die Hard');
		$this->run_test('The Toxic Avenger');*/

/*		$this->store($this->tags_vectors_index);*/

			/*while($tag_vector->length < 15) {
				$tag_vector[] = $math->random_int(990)+10 / 1000;
				$object->log('add to : '.$key);
			}*/
/*last point*/
	/*	foreach($this->tags_vectors_index as $key => $tag_vector) {
			foreach($tag_vector as $key => $value) {
				$tag_vector[$key] = $math->random_int(990)+10 / 1000;
			}
		}


		$this->denormalize($this->tags_vectors_index);
		$this->store();
	*&
		/*$test = [0.1, 0.2, 0.5, 0.6, 7];

		$object->log($object->toJSON($test));

		$this->denormalize_vertically($test);


		$object->log($object->toJSON($test));*/

		/*$this->train_super();*/

		/*$spliced = $object->create();

		foreach($this->tags_vectors_index as $index => $vector) {
			$spliced[$index] = $object->splice($vector, 0, 4);
		}

		$this->store($spliced);*/
		
		/*

		$this->run_test('Die Hard');

		$this->run_test('Death Wish');*/

			/*$counter_iteration++;
			$this->store($this->tags_vectors_index);
		}*/

		/*$this->store($this->tags_vectors_index);*/

		/*return $this->train();*/


		/*$last_vector = NULL;

		$vectors = [];

		foreach($this->tags_vectors_index as $v) {
			if($vectors->length < 100) {
				$vectors[] = $v;
			}
		}

		foreach($vectors as $tag => $vector) {
			if($last_vector != NULL) {
				$res = $this->vector->length_value($vector, $last_vector);
				$object->log($res);
			}
			$last_vector = $tag;
		}*/

		/*$object->log('run test');
		$self = $this;
		$self->run_test('Die Hard');
		$self->run_test('The Toxic Avenger');
		$self->run_test('Scream');
		$self->run_test('Faculty');
		$self->run_test('Phantoms');

		$self->run_test('Guardians of the Galaxy Volume 2');
		$self->run_test('Guardians of the Galaxy');
		$self->run_test('Captain America: The Winter Soldier');*/

		/*$vectors = $this->tags_vectors_index;

		foreach($vectors as $vector) {
			foreach($vector as $key => $value) {
				$vector[$key] = $value - (1/2);
				$object->log($value);
				$object->log($vector[$key]);
			}
		}

		$this->denormalize($this->tags_vectors_index);

		$this->store($this->tags_vectors_index);

		$self = $this;

		$object->log('start');

		$self->run_test('Die Hard');
		$self->run_test('The Toxic Avenger');
		$self->run_test('Scream');
		$self->run_test('Faculty');
		$self->run_test('Phantoms');

		$self->run_test('Guardians of the Galaxy Volume 2');
		$self->run_test('Guardians of the Galaxy');
		$self->run_test('Captain America: The Winter Soldier');*/

		$this->call_train(true);
	}
	/*1000 var*/
	/*350000*/

	/*fyrur combined 35000*/

	public $learning_rate = 15/*15*//*35*//*35*//*35*//*350*//*35000000*//*3500*//*3500*//*3500*/;/*3500*/ /*100*/ /*500;*/ /*2*1500*/ /*15;*//**500;*/ /*0.005;*/

	public $vector;

	public $last_total_error = (-1);

	public $current_index = /*1*/(-1);

	public function random_index($count) {
		return $this->current_index;
		/*$set_index = $this->current_index;
		$this->current_index += 1;
		if($this->current_index >= $count) {
			$this->current_index = 0;
		}
		return $set_index;*/
		return $math->random_int($count);
	}
	/*
						$row['intensity'],
						$row['seriousness'],
						$row['comedicity'],
						$row['absurdity'],
						$row['physicality'],
						$row['violence'],
						$row['action_value'],
						$row['romance'],
						$row['surprisinginess_predictability'],
						$row['scale'],
						$row['locality_globality'],
						$row['structure_randomness'],
						$row['intellectuality_mindlessness'],
						$row['rd1'],
						$row['rd2'],
						$row['rd3'],
						$row['rd4'],
						$row['rd5'],
						$row['rd6'],
						$row['rd7']*/

	public $set_columns = [
		/*'intensity',
		'seriousness',
		'comedicity',
		'absurdity',
		'physicality',
		'violence',
		'action_value',
		'romance',
		'surprisinginess_predictability',
		'scale',
		'locality_globality',
		'structure_randomness',
		'intellectuality_mindlessness',*/
		'rd1',
		'rd2',
		'rd3',
		'rd4',
		'rd5',
		'rd6',
		'rd7'
	];

	public function train_sub_item($item, $index_name=NULL, $exclude_extras=false, $set_tags_others=NULL, $combined=false) {
		/*$object->log('input');
		$object->log($object->toJSON($item));
		$object->log($object->toJSON($item['vector_value']));*/
		$set_all = false;
		/*if($object->isset($item['fixedposition']) && $item['fixedposition'] == 1) {
			$set_all = true;

		}*/
		$normalized = $this->vector->normalize_vector($item['vector_value']);
		/*$object->log($object->toJSON($normalized));*/

		/*$normalized = $item['vector_value'];*/

		$tag_total_vector = NULL;

		if($item['vector_value'] != NULL && $object->isset($item['connections'])) {
			$total_error = NULL;
			if($object->keys($item['connections'])->length == 0) {
				return false;
			}
			
			/*$object->dispatch_serial(function() {*/
				foreach($item['connections'] as $type => $movies) {
					foreach($movies as $movie) {
						if($total_error === NULL) {
							if($object->isset($movie['vector_value'])) {
								$total_error = $movie['vector_value'];
								$object->dispatch_serial(function() {
									$total_error = [...$total_error];
								});
								/*$total_error = [];

								foreach($movie['vector_value'] as $vector_item_value) {
									$total_error[] = $vector_item_value;
								}*/
							}
						} else {
							if($object->isset($movie['vector_value'])) {
								$object->dispatch_serial(function() {
									$total_error = $this->vector->add_vector($total_error, $movie['vector_value']);
								});
							}
						}
						/*if(false && $object->isset($movie['tags_vectors']) && $exclude_extras && $total_error != NULL) {

							foreach($movie['tags_vectors'] as $tag_value => $tag_item) {

								if($tag_value != $item['tag_value']) {
									if($object->isset($tag_item['vector_value'])) {
										if($tag_total_vector === NULL) {
											$tag_total_vector = $tag_item['vector_value'];
											$tag_total_vector = [...$tag_total_vector];
											/*$tag_total_vector = [];
											foreach($tag_item['vector_value'] as $vector_item_value) {
												$tag_total_vector[] = $vector_item_value;
											}///
										} else {
											$tag_total_vector = $this->vector->add_vector($tag_total_vector, $tag_item['vector_value']);
										}
									}
								}
							}

						}*/
					}
				}
			/*});*/

			$total_error = $this->vector->normalize_vector($total_error);



			if($tag_total_vector != NULL) {
				$tag_total_vector = $this->vector->normalize_vector($tag_total_vector);
				$total_error = $this->vector->subtract_vector($total_error, $tag_total_vector);
				/*$total_error = $this->vector->subtract_vector($tag_total_vector, $total_error);*/
				/*foreach($item['vector_value'] as $index => $column_value) {
					$item['vector_value'][$index] = $total_error[$index];
				}*/
			}/* else {
			}*/

			/*foreach($item['vector_value'] as $index => $column_value) {
				$item['vector_value'][$index] = $total_error[$index];
			}*/

			$self = $this;

			$tag_total_vector = $total_error;

			$tag_total_vector = $self->vector->normalize_vector($tag_total_vector);


			/*$movie_error = $self->vector->length_value($normalized_movie, $tag_total_vector);*/

			/*$object->log('movie error: '.$movie_error);*/

			$rate = 1 / $self->learning_rate;

			if($set_all) {
				$rate = 1;


			}

			/*$object->log($rate);*/

			$tag_total_vector = $self->vector->stretch_vector($tag_total_vector, $rate);

			/*$tag_total_vector = $self->vector->multiply_vector($tag_total_vector, $tag_total_vector);*/

			$addition = $self->vector->add_vector($normalized, $tag_total_vector);

			$addition = $self->vector->normalize_vector($addition);

			/*foreach($movie['vector_value'] as $index => $column_value) {
				$movie['vector_value'][$index] = $addition[$index];
			}*/


			/*if($movie_error != 'nan' && $movie_error != 'inf') {
				$set_total_error_value += $movie_error;
				$items_count++;
			}*/

			/*$object->log('before: '.$object->toJSON($item['vector_value']));*/
				$object->dispatch_serial(function() {
					foreach($item['vector_value'] as $index => $column_value) {
						$object->log('set item: '.$index);
						$item['vector_value'][$index] = $addition[$index];
					}
				});
			/*$object->log('added: '.$object->toJSON($item['vector_value']));*/

			return NULL;

			if($total_error != NULL && $item['vector_value']->length > 0) {
				/*$total_error = $this->vector->normalize_vector($total_error, true);*/

				if(!$combined) {
					$error_value = $this->vector->length_value($normalized, $total_error, $this->current_index);

					/*if($error_value > 10000) {
						$error_value = $error_value / 10000000000;
					}*/
					/*if($error_value < 10) {
						$error_value = $error_value * 1000000;
					}*/
					/*$object->log('error value : '.$error_value);*/

					/*$index = $this->random_index($item['vector_value']->length);*/

					/*$addition = $math->pow($error_value, 2) * ($item['vector_value'][$index]/($math->pow($math->abs($item['vector_value'][$index]), 1/2)));*/



					$index_values = $this->get_distribution($set_tags_others, $item['vector_value'], $error_value);

					$index_values['vector'] = $item['vector_value'];
					/*$object->log($index_values['vector']);
					$object->log($object->toJSON(['vector_value__' => $item['vector_value'], 'index_values__' => $index_values]));
					$object->log($object->toJSON($index_values['vector']));*/
					return $index_values;
				} else {

					$error_value = $this->vector->length_value($normalized, $total_error, (-1), true);

					/*$object->log($object->toJSON(['error value', $normalized, $total_error, $error_value]));*/
					/*if($error_value > 10000) {
						$error_value = $error_value / 10000000000;
					}*/
					/*if($error_value < 10) {
						$error_value = $error_value * 1000000;
					}*/

					$index_values_arr = [];

					foreach($item['vector_value'] as $index => $value) {
						/*if($index < 4) {*/
							$index_values = $this->get_distribution($set_tags_others, $item['vector_value'], $error_value, $index);
							$index_values_arr[] = $index_values;
						/*}*/
					}

					return $index_values_arr;
				}

				/*$index = $index_values['index'];
				$addition = $index_values['set_addition'];*/

				/*$addition = $item['vector_value'][$index] * ($error_value / ($math->pow($math->abs($error_value), 1/2)));*/
			
				/*if($object->isset($addition) && $addition != 'nan' && $addition > 0) {
					$addition = $addition / $this->learning_rate;
				}*/

				/*if($set_tags_others != NULL) {
					$max_distribution = -1;

					$set_value_index = 0;
					while($set_value_index < 20) {
						$item_vector_value_copy = [...$item['vector_value']];
						$item_vector_value_copy[$set_value_index] += $addition;

						$item_vector_value_copy = $this->vector->normalize_vector($item_vector_value_copy);

						$distribution_value = $this->get_distribution($set_tags_others, $item_vector_value_copy);
						if($distribution_value > $max_distribution) {
							$max_distribution = $distribution_value;
							$index = $set_value_index;
						}

						$set_value_index++;
					}
				}*/
				/*$object->log($addition);*/

				/*if($addition != 'nan') {
					$item['vector_value'][$index] += $addition;
				}

				$normalized = $this->vector->normalize_vector($item['vector_value'], true);
				foreach($normalized as $index => $value) {
					$item['vector_value'][$index] = $normalized[$index];
				}

				$this->errors[$item['tag_value']] = $addition;
				return $error_value;*/
			}
		}
		return NULL;
	}

	private $median_values = NULL;

	public function get_distribution($tags, $tag_item_vector_input, $error_value, $set_index=(-1)) {
		/*$index = $math->random_		*/
		$index = $this->random_index($this->set_columns->length);
		if($set_index != (-1)) {
			$index = $set_index;

			/*$index = $object->to_number($index);

			$object->log('index: '.$index);
			$object->log($object->toJSON($tag_item_vector_input));*/

			$addition = $this->get_error_addition_alt($error_value, $tag_item_vector_input[$index], $tag_item_vector_input);
			$addition = $addition / $this->learning_rate;

			/*$object->log($addition);*/

		} else {	
			/*$object->log('get error addition');
			$object->log($object->toJSON($tag_item_vector));*/

			$addition = $this->get_error_addition($error_value, $tag_item_vector_input[$index]);
			$addition = $addition / $this->learning_rate;

		}


		/*$object->log('vector_value');
		$object->log($tag_item_vector_input[$index]);

		$object->log('error_value error');
		$object->log($error_value);

		$object->log('addition');
		$object->log($addition);*/	
		/*$max_index = (-1);
		$max_distance = (-1);
		$set_addition = 0;

		$min_distance_vector = NULL;

		$min_distance = (-1);

		foreach($tags as $other_vector) {
			$distance += $this->vector->length_value($other_vector, $tag_item_vector_input);
			if($distance < $min_distance || $min_distance == (-1)) {
				$min_distance = $distance;
				$min_distance_vector = $other_vector;
			}
		}

		foreach($tag_item_vector_input as $index => $value) {
			$tag_item_vector = [...$tag_item_vector_input];


			$addition = $this->get_error_addition($error_value, $tag_item_vector[$index]);
			$addition = $addition / $this->learning_rate;

			$tag_item_vector[$index] += $addition;
			$tag_item_vector = $this->vector->normalize_vector($tag_item_vector, true);
			
			$distance = $this->vector->length_value($min_distance_vector, $tag_item_vector);

			if($max_distance == (-1) || $distance > $max_distance) {
				$max_distance = $distance;
				$max_index = $index;
				$set_addition = $addition;
			}
		}*/
		/*$object->log($max_distance);/*
		/*$object->log($object->toJSON(['max-index' => $max_index, 'distance' => $max_distance]));*/
		/*$set_addition = $set_addition*$max_distance;*/ /* / ($this->learning_rate);*/ /*$max_distance * */

		return ['index' => $index, 'set_addition' => $addition, 'error' => $error_value];
	}



	public function get_error_addition_alt($item_value, $error_value, $item_vector) {
		/*$object->log('input');
		$object->log($item_value);
		$object->log($error_value);
		$object->log($item_vector);*/
		/*$object->log($object->toJSON([$item_value, $error_value, $item_vector]));*/
		if($error_value == 'nan' || $item_value == 'nan' || $error_value <= 0 || $item_value <= 0) {
			return (-1);
		}

		/*$divisor = $math->pow($math->abs($item_value), 2);
		$addition = 0;
		if($divisor > 0 && $divisor < 1000) {
			$addition = $math->pow($math->abs($error_value), 1/2) / $divisor;
		} else {
			$addition = $math->pow($math->abs($error_value), 1/2) / 10000;
		}*/

		/*$addition = $math->pow($error_value, 1/2) * $math->pow($item_value, 2);*/


		/*$addition = $math->pow($item_value, 1/2) / $math->pow($error_value, 1/2);*/

		/*$addition = $this->get_error_addition($item_value, $error_value);*/


		/*$addition = $math->pow($item_value, 2) / $math->pow($error_value, 2);
	*/
		$addition = $math->pow($item_value, 2) / $math->pow($error_value, 2);

		/*$length = $this->vector->length_value($item_vector);

		$addition = $addition * $length;*/

		/*$addition = $addition / 1000;*/

		/*$object->log($object->toJSON(['itemvalue' => $error_value, 'error_value' => $item_value, 'addition' => $addition]));*/

		/*$object->log($addition);*/

		return $addition;
	}

	public function get_error_addition_alt_depr4($item_value, $error_value, $item_vector) {
		/*$addition = $this->get_error_addition($item_value, $error_value);
		return $addition;
		$length = $this->vector->length_value($item_vector);


		$addition = $addition / $length;

		return $addition;*/
		/*$object->log('input');
		$object->log($item_value);
		$object->log($error_value);
		$object->log($item_vector);*/
		/*$object->log($object->toJSON([$item_value, $error_value, $item_vector]));*/
		if($error_value == 'nan' || $item_value == 'nan' || $error_value <= 0 || $item_value <= 0) {
			return (-1);
		}

		/*$divisor = $math->pow($math->abs($item_value), 2);
		$addition = 0;
		if($divisor > 0 && $divisor < 1000) {
			$addition = $math->pow($math->abs($error_value), 1/2) / $divisor;
		} else {
			$addition = $math->pow($math->abs($error_value), 1/2) / 10000;
		}*/

		/*$addition = $math->pow($error_value, 1/2) * $math->pow($item_value, 2);*/


		$addition = $math->pow($item_value, 1/2) / $math->pow($error_value, 1/2);

		$length = $this->vector->length_value($item_vector);

		/*$object->log($length);*/

		$addition = $addition / $length;

		/*test_b*/
		/*$addition = $addition * $error_value;*/

		/*$addition = $addition / 1000;*/

		/*$object->log($addition);*/

		return $addition;
	}

	public function get_error_addition($item_value, $error_value) {
		/*$addition = $math->pow($error_value, 1/2) / ($item_value / $math->pow($math->abs($item_value), 2));*/
		/*$object->log('error addition');
		$object->log($error_value);
		$object->log($item_value);*/
		/*$object->log('item value:');
		$object->log($item_value);

		$object->log('error value:');
		$object->log($error_value);*/

		if($error_value == 'nan' || $item_value == 'nan' || $error_value <= 0 || $item_value <= 0) {
			return (-1);
		}
		/*$divisor = $math->pow($math->abs($item_value), 2);
		$addition = 0;
		if($divisor > 0 && $divisor < 1000) {
			$addition = $math->pow($math->abs($error_value), 1/2) / $divisor;
		} else {
			$addition = $math->pow($math->abs($error_value), 1/2) / 10000;
		}*/

		/*
		$error_value = $math->pow($error_value, 1/2);
		$item_value = $math->pow($item_value, 2);*/

		$error_value = $math->pow($error_value, 1/2);
		$item_value = $math->pow($item_value, 2);

		$addition = $item_value / $error_value;

		/*$object->log($addition);*/

		/*$object->log($object->toJSON([$error_value, $item_value, $addition]));*/
		/*$addition = $math->pow($error_value, 1/2) / $math->pow($math->abs($item_value), 2);*/
		/*if($item_value < 0) {
			$addition = (-1)*$addition;
		}*/
		/*$object->log('addition: '.$addition);*/

		return $addition;
	}
	/*mogulega skipta eftir 1/3 morkin*/
	/*private function get_error_addition($error_value, $item_value) {
		$addition = $math->pow($item_value, 2) * ($error_value / $math->pow($math->abs($error_value), 1/2));

		return $addition;
	}*/

	/*private function get_error_addition($error_value, $item_value) {
		$addition = ($item_value * $error_value) * ($error_value / $math->pow($math->abs($item_value), 1/2));

		return $addition;
	}*/

	/*public function train_sub_set($ids) {
		foreach($ids as $id) {
			$object->log('train sub set '.$id);
			foreach($this->vectors_by_type[$id] as $genre_title => $genre_item) {
				$this->train_sub_item($genre_item, true);
			}
		}
	}*/

	public function column_errors() {
		/*$index = $this->random_index($this->set_columns->length);*/

		$ignore_index = 0;

		$set_total_error_value = 0;

		$items_count = 0;

		$error_values = $object->create();

		while($ignore_index < 20) {
			$error_values[$ignore_index] = 0;

			foreach($this->vectors_by_type['movies'] as $title => $movie) {
				/*$object->log($title);
				$object->log($object->toJSON($movie['vector_value']));*/

				$movie_error = 0;

				/*$vector_value = $movie['vector_value'];

				$vector_value = [...$vector_value];*/

				$vector_value = [];

				foreach($movie['vector_value'] as $vector_item_value) {
					$vector_value[] = $vector_item_value;
				}

				if($vector_value->length > 0) {

					$object->splice($vector_value, $ignore_index, 1);

					$normalized_movie = $this->vector->normalize_vector($vector_value);

					/*$object->log($object->toJSON($normalized_movie));*/

					$tag_total_vector = NULL;

					if($object->isset($movie['tags_vectors'])) {



						foreach($movie['tags_vectors'] as $tag_value => $tag_item) {
							if($object->isset($tag_item['vector_value'])) {
								if($tag_total_vector === NULL && $tag_item['vector_value']->length > 0) {
									/*$tag_total_vector = $tag_item['vector_value'];
									$tag_total_vector = [...$tag_total_vector];*/
									$tag_total_vector = [];
									foreach($tag_item['vector_value'] as $tag_item_value) {
										$tag_total_vector[] = $tag_item_value;
									}

									$object->splice($tag_total_vector, $ignore_index, 1);
								} else if($tag_item['vector_value']->length > 0) {
									/*$tag_item_vector = $tag_item['vector_value'];
									$tag_item_vector = [...$tag_item_vector];*/
									$tag_total_vector = [];
									foreach($tag_item['vector_value'] as $tag_item_value) {
										$tag_total_vector[] = $tag_item_value;
									}

									$object->splice($tag_item_vector, $ignore_index, 1);

									$tag_total_vector = $this->vector->add_vector($tag_total_vector, $tag_item_vector);
								}
							}
						}

					}

					if($tag_total_vector != NULL && $movie['vector_value']->length > 0) {

						/*$object->log($object->toJSON($tag_total_vector));*/

						$tag_total_vector = $this->vector->normalize_vector($tag_total_vector);

						$movie_error = $this->vector->length_value($normalized_movie, $tag_total_vector);



						$error_values[$ignore_index] += $movie_error;
					}

				}
				/*x_value += error_value * x_value/√(abs(x_value)) * learning_rate*/

				/*return false;*/
			}
			$ignore_index++;
		}

		/*$object->log($object->toJSON($error_values));*/
		return $error_values;
	}

	public $total_run_count = 0;

	public function call_train($combined=true) {
		$this->train($combined);
	}

	public function train($combined=true) {
		$object->log('called train: '.$combined);


		/*$this->denormalize($this->tags_vectors_index);*/

/*		$this->run_test('Rush Hour');
		$this->run_test('Die Hard');
		$this->run_test('The Toxic Avenger');
		$this->run_test('Scream');
		$this->run_test('Faculty');
		$this->run_test('Phantoms');

		$this->run_test('Guardians of the Galaxy Volume 2');
		$this->run_test('Guardians of the Galaxy');
		$this->run_test('Captain America: The Winter Soldier');
*/
/*
		$this->store();

		return true;*/
		/*$this->current_index++;
		if($this->current_index >= 5) {
			$this->current_index = 0;
		}*/

		/*$counter_iteration = 0;*/


		/*$column_errors = $this->column_errors();

		$min_index = -1;

		$min_value_columns = -1;

		foreach($column_errors as $column_error_index => $column_error_value) {
			if($column_error_value > $min_value_columns || $min_value_columns == (-1)) {
				$min_index = $object->to_number($column_error_index);
				$min_value_columns = $column_error_value;
			}
		}

		$object->log('max index: '.$min_index.' '.$min_value_columns);*/

		/*while($counter_iteration < $iterations) {*/

		

		$wrap_count = [];

		$results_pool = [];

		$total_count = 
			$this->vectors_by_type['genres']->length
			+ $this->vectors_by_type['companies']->length
			+ $this->vectors_by_type['tropes']->length
			+ $this->vectors_by_type['popculture']->length
			+ $this->vectors_by_type['themes']->length
			/*+ $this->vectors_by_type['persons']->length*/
			;

		$self = $this;

		$results_callback = function() {
			/*$counts = $object->create();

			foreach($results_pool as $res_item) {
				$index = $res_item['res']['index'];
				$object->log($index);
				if(!$object->isset($counts[$index])) {
					$counts[$index] = 0;
				}
				$counts[$index]++;
			}

			$max_count = (-1);
			$max_index = (-1);

			$object->log('counts');

			foreach($counts as $index => $count) {
				$object->log($count);
				if($count > $max_count) {
					$max_index = $index;
					$max_count = $count;
				}
			}

			$object->log('max index');
			$object->log($max_index);

			$object->log($object->typeof($max_index));

			$max_index = $object->to_number($max_index);*/

			$set_total_error_value = 0;

			$items_count = 0;

			$object->log('execute movies');


			$sub_selection = $self->vectors_by_type['movies'];
			$sub_selection_length = $object->keys($sub_selection)->length;

			/*if($combined) {
				$sub_selection = $object->random_selection($sub_selection, 4, true);
			}*/
			$set_total_error_value_items = [];

			$total_completed_callback = function() {


				foreach($set_total_error_value_items as $set_error_item) {
					$set_total_error_value = $set_total_error_value + $set_error_item;
				}
				$object->log('total error');
				$object->log($set_total_error_value);

				$last = $self->last_total_error;

				$self->last_total_error = $set_total_error_value;
				if($last != (-1) && $last < $set_total_error_value) {
					/*$self->current_index++;
					if($self->current_index >= 5) {
						$self->current_index = 0;
					}*/
					/*$object->log('switch to : '.$self->current_index);
					$self->last_total_error = (-1);
					return false;*/
					$object->log('switch to : '.$self->current_index);
				}

				$object->log('error median');
				$error_value_median = $set_total_error_value / $sub_selection_length;
				$object->log($error_value_median);



				/*foreach($self->tags_vectors_index as $tag_value => $vector) {
					$normalized = $self->vector->normalize($vector);
					foreach($vector as $index => $value) {
						$vector[$index] = $normalized[$index];
					}
				}*/

				/*$self_instance = $self;*/
				$object->log('call denormalize');

				/*$self->denormalize($self->tags_vectors_index);*/

				/*
					$self->denormalize($self->tags_vectors_index);
					$self->store();
				*/

				$object->log('called denormalize');

				$object->denormalize = function($values) {
					$self->denormalize($values);
				};

				/*$last_callback = function($vector_index) {*/
					
				$object->log('continue and dispatch');
				$self->total_run_count++;
				if($self->total_run_count < 5) { /* var 5 */
					$object->log('call dispatch: '.$self->total_run_count);
					/*$object->dispatch($self->call_train, [true]);*/

					$wrap_call = async function() {
						$self->call_train();
						$object->dispose_parent($wrap_call);
					};

					$wrap_call();
				} else {
					$self->denormalize($self->tags_vectors_index);
					$self->store();

					/*$self->run_test('Friends');
					$self->run_test('Seinfeld');
					*/

					/*$self->run_test('Payback');
					$self->run_test('Bill & Ted'.$object->strings->apos().'s Excellent Adventur');
					$self->run_test('Spaceballs');
					$self->run_test('Half Baked');
					$self->run_test('Lethal Weapon 3');
					$self->run_test('Planes, Trains and Automobiles');
					$self->run_test('Faculty');
					$self->run_test('Slap Her... She'.$object->strings->apos().'s French');*/
				}
			};

			$wrap_item = /*async*/ function($title, $movie) {
				$movie_error = 0;
				$object->log($title);
				if($movie != NULL && $object->isset($movie['vector_value'])) {
					/*$object->log($movie);*/
					$normalized_movie = $movie['vector_value'];/*$this->vector->normalize_vector($movie['vector_value']);*/


					$tag_total_vector = NULL;


					if($object->isset($movie['tags_vectors'])) {

						foreach($movie['tags_vectors'] as $tag_value => $tag_item) {
							/*$object->log($tag_value);*/

							/*$test = $object->map($tag_item['vector_value'], function($e) {
								if($e == 'inf') {
									return -1;
								}
								return $e;
							});
							$object->log($object->toJSON([$tag_value, $test]));

							$object->log($object->toJSON([$tag_value, $tag_item['vector_value']]));*/
							if($object->isset($tag_item['vector_value'])) {
								if($tag_total_vector === NULL) {
									$tag_total_vector = $tag_item['vector_value'];
									$tag_total_vector = [...$tag_total_vector];
									/*$tag_total_vector = [];
									foreach($tag_item['vector_value'] as $tag_item_value) {
										$tag_total_vector[] = $tag_item_value;
									}*/
								} else {
									$tag_total_vector = $self->vector->add_vector($tag_total_vector, $tag_item['vector_value']);
								}
							}

							/*$object->log($object->toJSON([$tag_value, 'addition', $tag_total_vector]));*/
						}

					}

					if($tag_total_vector != NULL) {

						$tag_total_vector = $self->vector->normalize_vector($tag_total_vector);


						/*$object->log($object->toJSON($tag_total_vector));*/

						$movie_error = $self->vector->length_value($normalized_movie, $tag_total_vector);

						/*$object->log('movie error: '.$movie_error);*/

						$rate = 1 / $self->learning_rate;
						/*if($object->isset($movie['fixedposition']) && $movie['fixedposition'] == 1) {
							$rate = 1;
						}*/
						/*$object->log($rate);*/

						$tag_total_vector = $self->vector->stretch_vector($tag_total_vector, $rate);

						/*$object->log($object->toJSON($tag_total_vector));*/

						/*$tag_total_vector = $self->vector->multiply_vector($tag_total_vector, $tag_total_vector);*/

						$addition = $self->vector->add_vector($normalized_movie, $tag_total_vector);

						$addition = $self->vector->normalize($addition);

						/*$object->log('addition: '.$object->toJSON($addition));*/

						foreach($movie['vector_value'] as $index => $column_value) {
							/*$object->log($index);
							$object->log($column_value);
							$object->log($addition[$index]);*/
							$movie['vector_value'][$index] = $addition[$index];
						}


						/*$object->log('count: '.$items_count);*/

						/*if($movie_error != 'nan' && $movie_error != 'inf') {
							$items_count++;
						}*/

					} 
				}
				
				$set_total_error_value_items[] = $movie_error;
				$object->log('len: '.$set_total_error_value_items->length.' '.$sub_selection_length);
				if($set_total_error_value_items->length == $sub_selection_length) {
					$object->log('call total callback');
					$object->once($total_completed_callback);
				}
			};

			/*$partitions = [];

			if($object->isset($object->partitions_main)) {
				$partitions = $object->partitions_main;
			} else {*/
				$partitions = $object->partition_assoc($sub_selection, 3);
				/*$object->partitions_main = $partitions;
			}*/

			$partition_callback = async function($partition_value) {

				foreach($partition_value as $title => $movie) {
					$object->log('in title: '.$title);
					$wrap_item($title, $movie);
				}

			};

			foreach($partitions as $partition_item) {
				$partition_callback($partition_item);
			}				
					/*if($set_total_error_value != 'inf') {
					$self->total_run_count++;
					if($self->total_run_count < 20) {

						$object->dispatch($self->call_train, [$combined]);
					}
				}*/

			/*};*/

			/*$object->wordspace->perform_batch_processing($last_callback);*/


			/*
				$wrap($this->vectors_by_type['genres'], 'genres', false);
				$wrap($this->vectors_by_type['companies'], 'companies', false);
				$wrap($this->vectors_by_type['tropes'], 'tropes', true);
				$wrap($this->vectors_by_type['popculture'], 'popculture', true);
				$wrap($this->vectors_by_type['themes'], 'themes', true);
				$wrap($this->vectors_by_type['persons'], 'persons', false);
				$wrap($this->vectors_by_type['format'], 'format', false);
				$wrap($this->vectors_by_type['lists'], 'lists', false);*/


			/*bara ad nota genres, tropes popculture, themes, format og lists sem input i wordspace
			kannski eru forsetningarlidir margfaldadir*/



			/*$self->wordspace->perform_batch_processing(function($store_callback) {
				$object->log('in batch processing callback');
				$self->denormalize($self->tags_vectors_index);


				$self->denormalize($self->wordspace->all_vectors);


				$self->store();
				
				$store_callback();
				if($set_total_error_value != 'inf') {
					$self->total_run_count++;
					if($self->total_run_count < 2) {

						$object->dispatch($self->call_train, [$combined]);
					}
				}
			});*/

		};

		/*$test = 123;*/


		$call_results_callback = function() {

			$object->log('total count: '.$total_count);
			$object->log($wrap_count->length);
			$object->log($genre_name);

			$object->log($wrap_count->length);
			/*if($wrap_count->length == 8) {*/ /*$results_pool->length == $total_count && */
			$object->log('call results callback');
			$object->once($results_callback);
			/*$results_callback();*/
		
		};


		$wrap = async function($items, $genre_name, $flag) {
			$object->log('in wrap');
			$object->log($genre_name);
			/*$object->log($object->toJSON([$test, $genre_name]));
			$object->log($self);
			return false;*/
			$sub_selection = $items;
			/*if($combined) {
				$sub_selection = $object->random_selection($items, 4, true);
			}*/

			$object->log('items: '.$items->length);

			$callback_count = [];
			$callback_check_sub = function() {
				if($callback_count->length == $items->length) {
					$wrap_count[] = 1;

					$object->log('call results callback before : '.$wrap_count->length.' name: '.$genre_name);
					if($wrap_count->length == 8) {
						$object->log('call results callback');
						$object->once($results_callback);
					}
				}
			};

			/*$callback_check = function() {
			};*/

			$wrap_item_items = function($item) {
				$self->train_sub_item($item, $genre_name, $flag, $items, $combined);
				$callback_count[] = 1;
				/*$callback_check();*/


				$object->log('counts: '.$callback_count->length.' -' .$items->length);

				if($callback_count->length == $items->length) {
					$object->once($callback_check_sub);
				}
			};

			/*$partitions = [];

			if($object->isset($object->partitions_secondary)) {
				$partitions = $object->partitions_secondary;
			} else {*/
				$partitions = $object->partition($items, 2);
				/*$object->partitions_secondary = $partitions;
			}*/

			$partition_callback = async function($partition_value) {

				foreach($partition_value as $tag => $item) {
					/*$object->log($tag);
					$object->log($genre_name);
					$object->log($flag);
					$object->log($item);*/

					

					$wrap_item_items($item);
					/*if($res == NULL) {*/
						/*$object->log('res is null : '.$tag);*/
						/*$total_count--;*/	/*faera thessa virkni annad*/
					/*} else {*/
					/*if($res != NULL) {
						$results_pool[] = [
							'tag' => $tag,
							'res' => $res
						];
					}*/
				}
			};

			foreach($partitions as $partition) {
				$partition_callback($partition);
			}

		};

		$vectors_by_type = [
			'genres',
			'companies',
			'tropes',
			'popculture',
			'themes',
			'persons',
			'format',
			'lists'
		];

		$object->log('set total count : '.$total_count);

		/*foreach($vectors_by_type as $type) {
			foreach($this->vectors_by_type[$type] as $item) {
				if($item['vector_value'] == NULL || !$object->isset($item['movies']))  {
					$total_count--;
				}
			}
		}
		$total_count--;*/

		$object->log('set total count : '.$total_count);

		/*$wrap($this->vectors_by_type['persons'], 'persons', false);*/

		/*$object->set_call_count($wrap, 8);*/
		
		$wrap($this->vectors_by_type['genres'], 'genres', false);
		$wrap($this->vectors_by_type['companies'], 'companies', false);
		$wrap($this->vectors_by_type['tropes'], 'tropes', true);
		$wrap($this->vectors_by_type['popculture'], 'popculture', true);
		$wrap($this->vectors_by_type['themes'], 'themes', true);
		$wrap($this->vectors_by_type['persons'], 'persons', false);
		$wrap($this->vectors_by_type['format'], 'format', false);
		$wrap($this->vectors_by_type['lists'], 'lists', false);

		/*

format

lists
persons


*/

		/*foreach($this->vectors_by_type['genres'] as $genre_title => $genre_item) {
			$set_movie_error = $this->train_sub_item($genre_item, 'genres', false, $this->vectors_by_type['genres']);

			if($set_movie_error != 'nan') {
				$set_total_error_value += $set_movie_error;
			}
			$items_count++;

			$wrap($genre_item, 'genres', false, $this->vectors_by_type['genres'], $genre_title);
		}



		foreach($this->vectors_by_type['companies'] as $genre_title => $genre_item) {
			$set_movie_error = $this->train_sub_item($genre_item, 'companies', false, $this->vectors_by_type['companies']);


			if($set_movie_error != 'nan') {
				$set_total_error_value += $set_movie_error;
			}
			$items_count++;
		}

		foreach($this->vectors_by_type['persons'] as $genre_title => $genre_item) {
			$set_movie_error = $this->train_sub_item($genre_item, 'persons', false, $this->vectors_by_type['persons']);

			if($set_movie_error != 'nan') {
				$set_total_error_value += $set_movie_error;
			}
			$items_count++;
		}


		foreach($this->vectors_by_type['tropes'] as $genre_title => $genre_item) {
			$set_movie_error = $this->train_sub_item($genre_item, 'tropes', true, $this->vectors_by_type['tropes']);
			if($set_movie_error != 'nan') {
				$set_total_error_value += $set_movie_error;
			}
			$items_count++;
		}

		foreach($this->vectors_by_type['popculture'] as $genre_title => $genre_item) {
			$set_movie_error = $this->train_sub_item($genre_item, 'popculture', true, $this->vectors_by_type['popculture']);
			if($set_movie_error != 'nan') {
				$set_total_error_value += $set_movie_error;
			}
			$items_count++;
		}

		foreach($this->vectors_by_type['themes'] as $genre_title => $genre_item) {
			$set_movie_error = $this->train_sub_item($genre_item, 'themes', true, $this->vectors_by_type['themes']);
			if($set_movie_error != 'nan') {
				$set_total_error_value += $set_movie_error;
			}
			$items_count++;
		}
		
		$object->log('iteration : '.$counter_iteration);
		$object->log($set_total_error_value/$items_count);

		$object->log($set_total_error_value);

		$object->log($items_count);*/

		/*foreach($this->tags_vectors_index as $tag_value => $vector) {
			$normalized = $this->vector->normalize_vector($vector);
			foreach($vector as $index => $value) {
				$vector[$index] = $normalized[$index];
			}
		}*/
		$counter_iteration++;
		/*}*/

		return true;
		/*return ['tags' => $this->tags_vectors_index, 'errors' => $this->errors];*/

		/*$object->log($this->tags_vectors_index);
		$object->log($object->keys($this->tags_vectors_index)->length);

		foreach($this->tags_vectors_index as $tag_value => $vector) {*/
			/*$query = 'UPDATE tag_vectors SET ';

			$data_values = [...$vector];

			foreach($this->set_columns as $index => $column) {
				if($index > 0) {
					$query = $query.' , ';
				}
				$query = $query.' '.$column.' = ? ';
			}

			$query = $query.' WHERE tag_value = ?';

			$object->log($query);


			$data_values[] = $tag_value;

			$object->log($object->toJSON($data_values));*/

			/*$object->log($tag_value);
			$object->log($vector);
			$object->log($object->toJSON($vector));*/

			/*$query = 'UPDATE tag_vectors SET vector_value = ?, rd7 = 150 WHERE tag_value = ?';
			$this->data->execute($query, [$object->toJSON($vector), $tag_value]);*/

			/*$object->log('saved');*/
		/*}*/

	}

	public function denormalize_vertically_depr($vector_input) {
		$vectors = [];

		foreach($vector_input as $column_value) {
			$vectors[] = [$column_value];
		}

		$min_index = [(-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1)];
		$max_index = [(-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1)];

		foreach($vectors as $vector) {
			foreach($vector as $index => $value) {
				/*$index = $object->to_number($index);*/

				if($min_index[$index] == (-1) || $value < $min_index[$index]) {
					$min_index[$index] = $value;
				}
				if($max_index[$index] == (-1) || $value > $max_index[$index]) {
					$max_index[$index] = $value;
				}

			}
		}

		/*$object->log($object->toJSON([$min_index, $max_index]));*/

		$subtraction_index = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];

		foreach($min_index as $index => $min_index_value) {
			/*$index = $object->to_number($index);*/
			/*$object->log($object->toJSON([$min_index_value, $max_index[$index]]));*/
			if($max_index[$index] == $min_index_value) {
				$min_index[$index] = 1;
			} else {
				$min_index[$index] = 1 / ($max_index[$index] - $min_index_value);
			}
			$subtraction_index[$index] = $min_index_value; /** $min_index[$index];*/
			/*$object->log($object->toJSON([$subtraction_index[$index], $max_index[$index]]));*/
		}
		/*foreach($max_index as $index => $max_index_value) {
			$max_index[$index] = 10 / $max_index_value;
		}*/

		foreach($vectors as $vector) {
			foreach($vector as $index => $value) {
				/*$value = ($value - $subtraction_index[$index]);*/
				/*if($value == 0) {
					$value = 0.001;
				}*/
				$vector[$index] = $value * $min_index[$index];
			}

		}



		foreach($vector_input as $column => $old_value) {
			$vector_input[$column] = $vectors[$column][0];
		}
	}

	public function denormalize_vertically($vector) {
		$max_value = (-1);
		$min_value = (-1);
		foreach($vector as $index => $value) {
			if($max_value == (-1) || $value > $max_value) {
				$max_value = $value;
			}
			if($min_value == (-1) || $value < $min_value) {
				$min_value = $value;
			}
		}
		/*$object->log($object->toJSON([$min_value, $max_value]));*/
		if($max_value > 0 && $min_value < $max_value) {
			$divider = $max_value - $min_value;
			/*$object->log('divider: '.$divider);*/
			foreach($vector as $index => $value) {
				/*if($index < 5) {*/
					if($divider > 0) {
						/*$object->log($value);*/
						$value = $value - $min_value;
						/*if($value == 0) {
							$value = ;
						}*/

						/*$object->log($object->toJSON([$value, $divider]));*/

						$vector[$index] = (1/10000) + ($value / ($divider));
					}
				/*}*/
			}
		}
		/*$object->log($object->toJSON(['denormalize', $max_value, $min_value, $vector]));*/
	}

	public function denormalize_vertically_alt($vector) {
		$max_value = (-1);
		$min_value = (-1);
		foreach($vector as $index => $value) {
			if($max_value == (-1) || $value > $max_value) {
				$max_value = $value;
			}
			if($min_value == (-1) || $value < $min_value) {
				$min_value = $value;
			}
		}

		$range = $max_value - $min_value;
		$third = 1/25;
		/*if($range > $third) {
			return $vector;
		}*/
		/*$range = $range*2;*/
		/*$object->log($object->toJSON([$min_value, $max_value]));*/
		if($max_value > 0 && $min_value < $max_value) {
			$divider = $max_value - $min_value;
			$divider = $divider * 2;
			/*$object->log('divider: '.$divider);*/
			foreach($vector as $index => $value) {
				/*if($index < 5) {*/
					if($divider > 0) {
						/*$object->log($value);*/
						$value = $value - $min_value;
						/*if($value == 0) {
							$value = ;
						}*/

						/*$object->log($object->toJSON([$value, $divider]));*/

						$vector[$index] = (1/10000) + ($value / ($divider));
					}
				/*}*/
			}
		}
		/*$object->log($object->toJSON(['denormalize', $max_value, $min_value, $vector]));*/
	}

	public function denormalize($vectors) {
		/*foreach($vectors as $vector) {
			$this->denormalize_vertically($vector);

		}*/

		/*add26aug*/
		foreach($vectors as $vector) {
			foreach($vector as $key => $value) {
				$vector[$key] = $value + (1/2);
			}
		}

		$min_index = [(-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1)];
		$max_index = [(-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1), (-1)];

		foreach($vectors as $vector) {
			foreach($vector as $index => $value) {
				/*$index = $object->to_number($index);*/

				if($min_index[$index] == (-1) || $value < $min_index[$index]) {
					$min_index[$index] = $value;
				}
				if($max_index[$index] == (-1) || $value > $max_index[$index]) {
					$max_index[$index] = $value;
				}

			}
		}

		/*$object->log($object->toJSON([$min_index, $max_index]));*/

		$subtraction_index = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];

		foreach($min_index as $index => $min_index_value) {
			/*$index = $object->to_number($index);*/
			/*$object->log($object->toJSON([$min_index_value, $max_index[$index]]));*/
			if($max_index[$index] == $min_index_value) {
				$min_index[$index] = 1; /* / $max_index[$index];*/
			} else {
				$min_index[$index] = 1 / ($max_index[$index] - $min_index_value);
			}
			$subtraction_index[$index] = $min_index_value; /** $min_index[$index];*/
			/*$object->log($object->toJSON([$subtraction_index[$index], $max_index[$index]]));*/
		}
		/*foreach($max_index as $index => $max_index_value) {
			$max_index[$index] = 10 / $max_index_value;
		}*/

		foreach($vectors as $vector) {
			foreach($vector as $index => $value) {
				$value = ($value - $subtraction_index[$index]);
				/*if($value == 0) {
					$value = 0.005;
				}*/
				$vector[$index] = (1/10000) + ($value * $min_index[$index]);
			}
			$this->denormalize_vertically($vector);
		}

		foreach($vectors as $vector) {
			foreach($vector as $key => $value) {
				$vector[$key] = $value - (1/2);
			}
		}

		/*$partitioned = $object->partition($vectors, 6);

		$self = $this;

		$denormalized_completed = [];*/

		/*$wrap_partition = async function($partition) {
			foreach($partition as $vector) {
				$self->denormalize_vertically($vector);
			}
			$denormalized_completed[] = 1;
			if($denormalized_completed->length == 6) {
				$object->once($callback);
			}
		};

		foreach($partitioned as $partition) {
			$wrap_partition($partition);
		}*/
	}

	/*public function denormalize_vertically_alt($vector) {

	}*/

	public function store($tags=NULL) {
		if($tags == NULL) {
			$tags = $this->tags_vectors_index;
		}
		foreach($tags as $tag_value => $vector) {
			/*$object->log('store');
			$object->log($tag_value);
			$object->log($object->toJSON($vector));*/
			/*$query = 'UPDATE tag_vectors SET ';

			$data_values = [...$vector];

			foreach($this->set_columns as $index => $column) {
				if($index > 0) {
					$query = $query.' , ';
				}
				$query = $query.' '.$column.' = ? ';
			}

			$query = $query.' WHERE tag_value = ?';

			$object->log($query);


			$data_values[] = $tag_value;

			$object->log($object->toJSON($data_values));*/
			/*$all_same = true;
			foreach($vector['vector_value'] as $index => $value) {
				if($value != 0) {
					$all_same = false;
				}
			}*/

			/*if($all_same) {
				$object->log('reset: '.$tag_value);
				foreach($vector as $index => $value) {
					$vector[$index] = ($math->random_int(990)+10) / 1000;
				}
			}*/

			/*$object->log($object->toJSON([$vector['vector_value'], $tag_value]));*/

			$query = 'UPDATE tag_vectors SET vector_value = ? WHERE tag_value = ?';
			/*$vector = $this->vector->normalize_vector($vector);*/
			$values_query = [$object->toJSON($vector['vector_value']), $tag_value];
			$this->data->execute($query, $values_query);

			/*$object->log('saved');*/
		}
		$object->log('stored');

		/*$query = 'UPDATE tag_vectors SET fixedposition = 0';
		$this->data->execute($query, []);*/

		/*$debug_test = $object->toJSON($tags);
		$object->log($debug_test);*/
		/*$debug_test = $object->fromJSON($debug_test);
		$object->log($object->values($debug_test)->length);

		$debug_test_2 = $object->toJSON($debug_test);
		$object->log($debug_test_2);

		$object->log($object->keys($debug_test)->length);*/
		/*$query = 'SELECT * FROM medias';
		$rows = $this->data->get_rows($query, []);*/
	}

	public $tag_type_index;

	public function train_super() {
		$self = $this;
		$super_vector = [1, 1, 1, 1];
		if($object->isset($this->tags_vectors_index['SUPER_'])) {
			$super_vector = $this->tags_vectors_index['SUPER_'];
		}/* else {
			$super_vector = [
				$math->random_int(1000) / 1000,
				$math->random_int(1000) / 1000,
				$math->random_int(1000) / 1000,
				$math->random_int(1000) / 1000
			];

		}*/
		$this->tags_vectors_index['SUPER_'] = $super_vector;

		$this->tags_vectors_index['SUPER_'] = $this->vector->normalize($super_vector);
		$super_vector = $this->tags_vectors_index['SUPER_'];

		$object->log($object->toJSON($super_vector));

		/*return false;*/

		$object->log('go1');

		$iteration = 0;
		$max_iterations = 1;

		while($iteration < $max_iterations) {
			$column_errors = [0, 0, 0, 0];
			$total_movies = [0, 0, 0, 0];

			foreach($self->vectors_by_type['movies'] as $title => $movie) {

				$movie_error = 0;

				/*$normalized_movie = $movie['vector_value'];*/
				$normalized_movie = $this->vector->normalize_vector($movie['vector_value']);

				$total_movies = $this->vector->add_vector($total_movies, $normalized_movie);

				$tag_total_vector = NULL;

				if($object->isset($movie['tags_vectors'])) {



					foreach($movie['tags_vectors'] as $tag_value => $tag_item) {
						if($object->isset($tag_item['vector_value'])) {
							if($tag_total_vector === NULL) {
								$tag_total_vector = $tag_item['vector_value'];
								$tag_total_vector = [...$tag_total_vector];
							} else {
								$tag_total_vector = $self->vector->add_vector($tag_total_vector, $tag_item['vector_value']);
							}
						}
					}

					$set_index_value = 0;
					while($set_index_value < 7) {

						/*if($index != 4 && $index != 6) {*/
						$tag_results = [];

						foreach($tag_total_vector as $index => $column_value) {
							$tag_results[] = $super_vector[$index] * $column_value;
						}

						$set_movie_values = [
							$normalized_movie[$set_index_value],
							$normalized_movie[$set_index_value],
							$normalized_movie[$set_index_value],
							$normalized_movie[$set_index_value]
						];


						/*$object->log($object->toJSON([$tag_results, $set_movie_values]));*/

						foreach($tag_results as $index => $value) {
							$len = $this->vector->length_value($set_movie_values, $tag_results, $index);
							$column_errors[$set_index_value] += $len;

							/*$object->log($len);*/
						}

						$set_index_value++;
					}

				}



				/*$object->log('error: '.$error);*/

				/*$tag_total_vector = $self->vector->normalize_vector($tag_total_vector);*/

				/*if($tag_total_vector != NULL && $movie['vector_value']->length > 0) {


					$tag_total_vector = $self->vector->normalize_vector($tag_total_vector);

					$movie_error = $self->vector->length_value($normalized_movie, $tag_total_vector, $self->current_index);

				}*/

			}
			$object->log($object->toJSON($column_errors));

			$iteration++;
		}

		foreach($column_errors as $index => $value) {
			$super_vector[$index] = $value;
		}
		$object->log($object->toJSON($super_vector));
	}
}

?>