Merge branch 'master' into genetic_algorithm

This commit is contained in:
s452645 2021-06-17 12:04:08 +02:00
commit 120cc7489e
1376 changed files with 4888 additions and 12097 deletions

3
.gitignore vendored
View File

@ -145,3 +145,6 @@ cython_debug/
# local sandbox
sandbox/
/algorithms/learn/decision_tree/decistion_tree.png
/resources/data/neural_network/specificity/train
/resources/data/neural_network/series/train/

Binary file not shown.

View File

@ -1,24 +1,25 @@
import os
import json
from matplotlib import pyplot
from joblib import dump, load
from sklearn import tree
from sklearn.feature_extraction import DictVectorizer
from objects.mines.disarming.mine_parameters import MineParameters
from objects.mines.disarming.parameter_json import generate_data
from disarming.parameters.mine_parameters import MineParameters
from disarming.parameters.parameter_json import generate_data
class DecisionTree:
def __init__(self, clf_source: str = None, vec_source: str = None):
if clf_source is not None and vec_source is not None:
def __init__(self, load_from_file: bool = False):
if load_from_file:
clf_source = r"algorithms/learn/decision_tree/decision_tree.joblib"
vec_source = r"algorithms/learn/decision_tree/dict_vectorizer.joblib"
self.load(clf_source, vec_source)
else:
self.clf = None
self.vec = None
def build(self, training_file: str, depth: int):
path = os.path.join("..", "..", "resources", "data", training_file)
path = os.path.join("../..", "..", "resources", "data", "decision_tree", training_file)
samples = list()
results = list()
@ -40,12 +41,12 @@ class DecisionTree:
print(tree.export_text(self.clf, feature_names=self.vec.get_feature_names()))
# plot a tree (not necessary)
fig = pyplot.figure(figsize=(50, 40))
_ = tree.plot_tree(self.clf,
feature_names=self.vec.get_feature_names(),
class_names=self.clf.classes_,
filled=True)
fig.savefig("decistion_tree.png")
# fig = pyplot.figure(figsize=(50, 40))
# _ = tree.plot_tree(self.clf,
# feature_names=self.vec.get_feature_names(),
# class_names=self.clf.classes_,
# filled=True)
# fig.savefig("decistion_tree.png")
def save(self):
dump(self.clf, 'decision_tree.joblib')
@ -84,8 +85,8 @@ class DecisionTree:
if __name__ == "__main__":
# generate_data("training_set.txt", 12000)
generate_data("training_set.txt", 4500)
decision_tree = DecisionTree()
decision_tree.build("training_set.txt", 15)
decision_tree.test()
# decision_tree.save()
decision_tree.save()

Binary file not shown.

View File

@ -0,0 +1,135 @@
import numpy as np
import joblib
import pathlib
import tensorflow as tf
from enum import Enum
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.models import Sequential
# int value is a number of classes
class NNType(Enum):
SERIES = "series", 4,
SPECIFICITY = "specificity", 3
class NeuralNetwork:
def __init__(self, network_type: NNType, load_from_file: bool = False, img_height=180, img_width=180):
self.type = network_type
self.training_data_dir = pathlib.Path(fr"../../../resources/data/neural_network/{self.type.value[0]}/train")
self.img_height = img_height
self.img_width = img_width
if load_from_file:
saved_model_path = fr"algorithms/learn/neural_network/{self.type.value[0]}/saved_model.h5"
classes_path = fr"algorithms/learn/neural_network/{self.type.value[0]}/saved_model_classes.joblib"
self.load(saved_model_path, classes_path)
else:
self.model = None
self.class_names = None
def build(self, epochs=15, batch_size=32):
num_classes = self.type.value[1]
train_ds = tf.keras.preprocessing.image_dataset_from_directory(
self.training_data_dir,
validation_split=0.2,
subset="training",
seed=123,
image_size=(self.img_height, self.img_width),
batch_size=batch_size)
self.class_names = train_ds.class_names
val_ds = tf.keras.preprocessing.image_dataset_from_directory(
self.training_data_dir,
validation_split=0.2,
subset="validation",
seed=123,
image_size=(self.img_height, self.img_width),
batch_size=batch_size)
autotune = tf.data.AUTOTUNE
train_ds = train_ds.cache().shuffle(1000).prefetch(buffer_size=autotune)
val_ds = val_ds.cache().prefetch(buffer_size=autotune)
data_augmentation = keras.Sequential(
[
layers.experimental.preprocessing.RandomFlip("horizontal",
input_shape=(self.img_height,
self.img_width,
3)),
layers.experimental.preprocessing.RandomRotation(0.1),
layers.experimental.preprocessing.RandomZoom(0.1),
]
)
model = Sequential([
data_augmentation,
layers.experimental.preprocessing.Rescaling(1. / 255),
layers.Conv2D(16, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Conv2D(32, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Conv2D(64, 3, padding='same', activation='relu'),
layers.MaxPooling2D(),
layers.Dropout(0.2),
layers.Flatten(),
layers.Dense(128, activation='relu'),
layers.Dense(num_classes)
])
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
model.summary()
model.fit(
train_ds,
validation_data=val_ds,
epochs=epochs
)
self.model = model
def save(self):
self.model.save(fr"{self.type.value[0]}/saved_model.h5")
joblib.dump(self.class_names, fr"{self.type.value[0]}/saved_model_classes.joblib")
def load(self, model_path, classes_path):
self.model = tf.keras.models.load_model(model_path)
self.class_names = joblib.load(classes_path)
def get_answer(self, image_path):
img = keras.preprocessing.image.load_img(
image_path, target_size=(self.img_height, self.img_width)
)
img_array = keras.preprocessing.image.img_to_array(img)
img_array = tf.expand_dims(img_array, 0)
predictions = self.model.predict(img_array)
score = tf.nn.softmax(predictions[0])
# returns class, condifdence
return self.class_names[np.argmax(score)], 100 * np.max(score)
if __name__ == "__main__":
# Building and saving a new model:
# (requires a valid training set in resources/data/neural_network/train)
# neural_network = NeuralNetwork(NNType.SERIES)
# neural_network.build(epochs=10)
# neural_network.save()
# Loading a model from file:
neural_network = NeuralNetwork(NNType.SPECIFICITY, load_from_file=True)
# Test
image = r"../../../resources/data/neural_network/specificity/disarm/tanks/1-35-British-Tank-FV-214-Conqueror-MK-II-Amusing-Hobby-35A027-AH-35A027_b_0.JPG"
neural_network.get_answer(image)

Binary file not shown.

View File

@ -3,9 +3,9 @@ import pygame
import project_constants as const
from assets import asset_constants as asset
from objects.mines.mine_models.standard_mine import StandardMine
from objects.mines.mine_models.chained_mine import ChainedMine
from objects.mines.mine_models.time_mine import TimeMine
from objects.mine_models.standard_mine import StandardMine
from objects.mine_models.chained_mine import ChainedMine
from objects.mine_models.time_mine import TimeMine
# ================================= #

View File

@ -0,0 +1,90 @@
import os
import copy
import random
from disarming.parameters.hash_function import SeriesHash, SpecificityHash
from objects.mine_models.mine import Mine
from algorithms.learn.decision_tree.decision_tree import DecisionTree
from algorithms.learn.neural_network.neural_network import NNType, NeuralNetwork
SERIES_IMAGES_PATH = r"resources/data/neural_network/series/disarm"
SPECIFICITY_IMAGES_PATH = r"resources/data/neural_network/specificity/disarm"
class_to_series = \
{SeriesHash[name].value[2]: SeriesHash[name].value[1] for name, _ in SeriesHash.__members__.items()}
class_to_specificity = \
{SpecificityHash[name].value[2]: SpecificityHash[name].value[1] for name, _ in SpecificityHash.__members__.items()}
class DisarmingHandler:
def __init__(self, mine: Mine):
self.mine = mine
self.mine_params = dict()
self.series_img = None
self.specificity_img = None
self.recognized_series = None
self.recognized_specificity = None
self.correct_wire = None
self.chosen_wire = None
self._set_mine_params()
self._set_correct_wire()
def _set_mine_params(self):
self.mine_params = self.mine.investigate()
def _set_correct_wire(self):
self.correct_wire = self.mine.wire
def get_mine_params(self):
return [self.mine_params["mine_type"], self.mine_params["weight"], self.mine_params["danger_cls"],
self.mine_params["indicator"], self.mine_params["series"], self.mine_params["specificity"]]
def pick_series_image(self):
series_class = SeriesHash[self.mine_params["series"].upper().replace(" ", "_")].value[2]
imgs_dir = os.path.join(SERIES_IMAGES_PATH, series_class)
self.series_img = os.path.join(
imgs_dir, random.choice([x for x in os.listdir(imgs_dir) if os.path.isfile(os.path.join(imgs_dir, x))]))
return self.series_img
def pick_specificity_image(self):
specificity_class = SpecificityHash[self.mine_params["specificity"].upper().replace(" ", "_")].value[2]
imgs_dir = os.path.join(SPECIFICITY_IMAGES_PATH, specificity_class)
self.specificity_img = os.path.join(
imgs_dir, random.choice([x for x in os.listdir(imgs_dir) if os.path.isfile(os.path.join(imgs_dir, x))]))
return self.specificity_img
def recognize_series(self):
nn = NeuralNetwork(NNType.SERIES, load_from_file=True)
answer, confidence = nn.get_answer(self.series_img)
self.recognized_series = class_to_series[answer]
return self.recognized_series, self.mine_params["series"] == self.recognized_series
def recognize_specificity(self):
nn = NeuralNetwork(NNType.SPECIFICITY, load_from_file=True)
answer, confidence = nn.get_answer(self.specificity_img)
self.recognized_specificity = class_to_specificity[answer]
return self.recognized_specificity, self.mine_params["specificity"] == self.recognized_specificity
def choose_wire(self):
dt = DecisionTree(load_from_file=True)
agent_params = copy.deepcopy(self.mine_params)
agent_params["series"] = self.recognized_series
agent_params["specificity"] = self.recognized_specificity
self.chosen_wire = dt.get_answer(agent_params)[0]
return self.chosen_wire
def defuse(self):
return self.mine.disarm(self.chosen_wire)

View File

@ -5,6 +5,9 @@ class Wire(Enum):
BLUE = 1, "blue"
GREEN = 2, "green"
RED = 3, "red"
YELLOW = 4, "yellow"
WHITE = 5, "white"
PURPLE = 6, "purple"
class TypeHash(Enum):
@ -23,14 +26,10 @@ class DangerClassHash(Enum):
class SeriesHash(Enum):
TCH_2990TONER = 128, "TCH 2990toner"
TCH_2990INKJET = 110, "TCH 2990inkjet"
TVY_2400H = 100, "TVY 2400h"
SWX_5000 = 80, "SWX 5000"
SWX_4000 = 50, "SWX 4000"
WORKHORSE_3200 = 30, "WORKHORSE 3200"
FX_500 = 15, "FX 500"
TVY_2400 = 0, "TVY 2400"
TCH_2990TONER = 220, "TCH 2990toner", "T"
SWX_5000 = 168, "SWX 5000", "S"
WORKHORSE_3200 = 94, "WORKHORSE 3200", "W"
FX_500 = 1, "FX 500", "F"
class IndicatorHash(Enum):
@ -42,13 +41,9 @@ class IndicatorHash(Enum):
class SpecificityHash(Enum):
ANTI_AIRCRAFT = 55, "anti aircraft"
ANTI_PERSONNEL = 43, "anti personnel"
DEPTH_MINE = 37, "depth mine"
ANTI_TANK = 26, "anti tank"
PROXIMITY_MINE = 18, "proximity mine"
PRESSURE_MINE = 9, "pressure mine"
FRAGMENTATION_MINE = 0, "fragmentation mine"
ANTI_AIRCRAFT = 512, "anti aircraft", "planes"
DEPTH_MINE = 256, "depth mine", "ships"
ANTI_TANK = 16, "anti tank", "tanks"
class WeightHash(Enum):
@ -68,10 +63,16 @@ MAX_VALUE = max([elem.value[0] for elem in TypeHash]) \
def _get_wire_color(hash_sum):
if hash_sum < 0.43 * MAX_VALUE:
if hash_sum < 0.20 * MAX_VALUE:
return Wire.BLUE
elif hash_sum <= 0.56 * MAX_VALUE:
elif hash_sum <= 0.38 * MAX_VALUE:
return Wire.GREEN
elif hash_sum <= 0.50 * MAX_VALUE:
return Wire.YELLOW
elif hash_sum <= 0.60 * MAX_VALUE:
return Wire.WHITE
elif hash_sum <= 0.80 * MAX_VALUE:
return Wire.PURPLE
else:
return Wire.RED

View File

@ -1,5 +1,5 @@
import random
from objects.mines.disarming import hash_function as hf
from disarming.parameters import hash_function as hf
class MineParameters:

View File

@ -1,10 +1,10 @@
import json
import objects.mines.disarming.mine_parameters as param
import disarming.parameters.mine_parameters as param
import os
import project_constants as const
# this module is self contained, used to generate a json file
DIR_DATA = os.path.join(const.ROOT_DIR, "resources", "data")
DIR_DATA = os.path.join(const.ROOT_DIR, "resources", "data", "decision_tree")
# just to show, how mine parameters works

View File

@ -1,8 +1,10 @@
import pygame
import pygame_gui
from project_constants import SCREEN_WIDTH, SCREEN_HEIGHT, V_NAME_OF_WINDOW
from assets.asset_constants import ASSET_CONCRETE
from project_constants import SCREEN_WIDTH, SCREEN_HEIGHT, V_NAME_OF_WINDOW
from objects.mine_models.mine import Mine
from disarming.disarming_handler import DisarmingHandler
# =========== #
# == const == #
@ -77,7 +79,7 @@ class SampleWindow:
# main attributes
self.running = True
self.clock = pygame.time.Clock()
self.manager = pygame_gui.UIManager(screen_size, 'theme.json') # TODO : change theme path
self.manager = pygame_gui.UIManager(screen_size, 'disarming/theme.json') # TODO : change theme path
# main attributes
def gui():
@ -206,7 +208,7 @@ class SampleWindow:
(x_cables, y_cables_label1),
size_cable_label
),
text="CORRECT CABLE",
text="CORRECT WIRE",
manager=self.manager,
object_id="description"
)
@ -215,7 +217,7 @@ class SampleWindow:
(x_cables, y_cables_label2),
size_cable_label
),
text="CHOSEN CABLE",
text="CHOSEN WIRE",
manager=self.manager,
object_id="description"
)
@ -276,6 +278,16 @@ class SampleWindow:
manager=self.manager,
object_id="empty_field"
)
surf = pygame.Surface(size_image)
surf.fill((20, 20, 20))
pygame_gui.elements.UIImage(
image_surface=surf,
relative_rect=pygame.Rect(
(x_image1, y_image),
size_image
),
manager=self.manager
)
def image2():
pygame_gui.elements.UILabel(
@ -315,6 +327,16 @@ class SampleWindow:
manager=self.manager,
object_id="empty_field"
)
surf = pygame.Surface(size_image)
surf.fill((20, 20, 20))
pygame_gui.elements.UIImage(
image_surface=surf,
relative_rect=pygame.Rect(
(x_image2, y_image),
size_image
),
manager=self.manager
)
params_desc()
params_values()
@ -391,25 +413,32 @@ class SampleWindow:
object_id="field"
)
def show_pic_series(self, pic: pygame.Surface):
def blit_pic(self, x_image, pic):
# initializing surface with background
surf = pygame.Surface(size_image)
surf.blit(pygame.transform.scale(pic, size_image), (0, 0))
pygame_gui.elements.UIImage(
image_surface=surf,
relative_rect=pygame.Rect(
(x_image1, y_image),
size_image
),
manager=self.manager
surf.fill((20, 20, 20))
# scaling size & coords
bigger = max(pic.get_size()[0], pic.get_size()[1])
scaling_factor = (height_image - 10) / bigger
length_pic = int(pic.get_size()[0]*scaling_factor)
height_pic = int(pic.get_size()[1]*scaling_factor)
size_pic = (length_pic, height_pic)
coords_pic = (
int((length_image-length_pic) / 2),
int((height_image-height_pic) / 2)
)
def show_pic_spec(self, pic: pygame.Surface):
surf = pygame.Surface(size_image)
surf.blit(pygame.transform.scale(pic, size_image), (0, 0))
# blitting the image onto background
surf.blit(pygame.transform.scale(pic, size_pic), coords_pic)
pygame_gui.elements.UIImage(
image_surface=surf,
relative_rect=pygame.Rect(
(x_image2, y_image),
(x_image, y_image),
size_image
),
manager=self.manager
@ -501,49 +530,66 @@ class SampleWindow:
# == run == #
# ========= #
def run(self):
def run(self, mine: Mine):
timed_event = pygame.USEREVENT + 1
pygame.time.set_timer(timed_event, 6000)
step = 0
handler = DisarmingHandler(mine)
while self.running:
time_delta = self.clock.tick(60) / 1000.0
keystate = pygame.key.get_pressed()
# all events except QUIT are for testing
for event in pygame.event.get():
if event.type == pygame.QUIT:
self.running = False
if keystate[pygame.K_a]:
self.show_params("hello", "yello", "gel", "jello", "yum", "hello")
if keystate[pygame.K_s]:
self.show_series("workhorse 3200wx", True)
if keystate[pygame.K_d]:
self.show_spec("anti aircraft", False)
if keystate[pygame.K_f]:
self.show_cable_calculated("red")
if keystate[pygame.K_g]:
self.show_cable_chosen("blue")
if keystate[pygame.K_q]:
self.show_pic_series(ASSET_CONCRETE)
if keystate[pygame.K_w]:
self.show_pic_spec(ASSET_CONCRETE)
if event.type == timed_event:
if step == 0: # just the params
params = handler.get_mine_params()
self.show_params(params[0], params[1], params[2], params[3], params[4], params[5])
elif step == 1: # correct cable
self.show_cable_calculated(handler.correct_wire)
elif step == 2: # loading the letter image
img = pygame.image.load(handler.pick_series_image())
self.blit_pic(x_image1, img)
elif step == 3: # recognising the letter
answer, is_correct = handler.recognize_series()
self.show_series(answer, is_correct)
elif step == 4: # loading spec image
img = pygame.image.load(handler.pick_specificity_image())
self.blit_pic(x_image2, img)
elif step == 5: # recognising spec image
answer, is_correct = handler.recognize_specificity()
self.show_spec(answer, is_correct)
elif step == 6: # showing the chosen cable
self.show_cable_chosen(handler.choose_wire())
else:
self.running = False
step += 1
self.manager.update(time_delta)
self.window_surface.blit(self.background, (0, 0))
self.manager.draw_ui(self.window_surface)
pygame.display.update()
return handler.defuse()
def disarming_popup():
def disarming_popup(mine: Mine = None):
# run the pop-up
app = SampleWindow()
app.run()
result = app.run(mine)
# bring display back to normal
pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption(V_NAME_OF_WINDOW)
return result
if __name__ == '__main__':
pygame.init()

View File

@ -71,6 +71,27 @@
{
"dark_bg": "#804e46"
}
},
"yellow":
{
"colours":
{
"dark_bg": "#7d803e"
}
},
"purple":
{
"colours":
{
"dark_bg": "#733c78"
}
},
"white":
{
"colours":
{
"dark_bg": "#7d7d7d"
}
}
}

View File

@ -7,7 +7,7 @@ from algorithms.search import a_star
from minefield import Minefield
from objects.mines.mine_models.time_mine import TimeMine
from objects.mine_models.time_mine import TimeMine
from ui.ui_components_manager import UiComponentsManager
from ui.text_box import TextBox

View File

@ -7,9 +7,9 @@ import project_constants as const
from objects.tile import Tile
# import mine models
from objects.mines.mine_models.standard_mine import StandardMine
from objects.mines.mine_models.time_mine import TimeMine
from objects.mines.mine_models.chained_mine import ChainedMine
from objects.mine_models.standard_mine import StandardMine
from objects.mine_models.time_mine import TimeMine
from objects.mine_models.chained_mine import ChainedMine
class JsonGenerator:

View File

@ -1,6 +1,6 @@
import project_constants as const
from objects import tile as tl, agent as ag
from objects.mines.mine_models.time_mine import TimeMine
from objects.mine_models.time_mine import TimeMine
import json_generator as jg

View File

@ -3,7 +3,9 @@ from assets import asset_constants as asset
import json
from time import sleep
from pygame import transform
from algorithms.learn.decision_tree import DecisionTree
import disarming.popup as popup
from algorithms.learn.decision_tree.decision_tree import DecisionTree
# Class of our agent, initialization of it
@ -21,21 +23,16 @@ class Agent:
self.row, self.column = int(self.row), int(self.column)
self.position = [self.row, self.column]
self.on_screen_coordinates = const.get_tile_coordinates(tuple(self.position))
self.decision_tree = DecisionTree(const.ROOT_DIR + "/algorithms/learn/decision_tree.joblib",
const.ROOT_DIR + "/algorithms/learn/dict_vectorizer.joblib")
self.direction = const.Direction(data["agents_initial_state"]["direction"])
self.rotation_angle = -const.Direction(self.direction).value * 90
self.going_forward = False
self.rotating_left = False
self.rotating_right = False
def defuse_a_mine(self, mine):
mine_params = mine.investigate()
chosen_wire = self.decision_tree.get_answer(mine_params)
# TODO temporarily printing chosen wire
print("agent's chosen wire: " + str(chosen_wire[0]))
sleep(3)
return mine.disarm(chosen_wire)
@staticmethod
def defuse_a_mine(mine):
is_success = popup.disarming_popup(mine)
return is_success
def update_and_draw(self, window, delta_time, minefield):
self.update(delta_time, minefield)

View File

View File

@ -2,7 +2,7 @@
from __future__ import annotations
from .mine import Mine
from objects.mines.disarming.hash_function import TypeHash
from disarming.parameters.hash_function import TypeHash
class ChainedMine(Mine):

View File

@ -4,7 +4,7 @@ from abc import ABC, abstractmethod
# type hints
from typing import Tuple
from objects.mines.disarming.mine_parameters import MineParameters
from disarming.parameters.mine_parameters import MineParameters
# Mine cannot be instantiated
# all abstract methods must be implemented in derived classes
@ -34,7 +34,4 @@ class Mine(ABC):
del mine_parameters["wire"]
self.wire = wire
# TODO temporarily printing parameters and right wire
print("parameters:", mine_parameters, "\nright wire: " + wire)
return mine_parameters

View File

@ -1,5 +1,5 @@
from .mine import Mine
from objects.mines.disarming.hash_function import TypeHash
from disarming.parameters.hash_function import TypeHash
class StandardMine(Mine):

View File

@ -1,5 +1,5 @@
from .mine import Mine
from objects.mines.disarming.hash_function import TypeHash
from disarming.parameters.hash_function import TypeHash
class TimeMine(Mine):

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 958 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 896 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 893 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 987 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 916 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 912 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 927 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 900 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 849 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 889 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 925 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 910 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 908 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 923 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 992 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 899 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 924 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 833 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 839 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 884 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 826 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 838 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 915 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 883 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 960 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 946 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 998 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 928 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 925 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 953 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1009 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 996 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 953 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 981 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1017 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 930 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 955 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 958 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 966 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 882 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 927 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 907 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 949 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1014 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 962 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 976 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 948 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 868 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 936 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 852 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 800 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 806 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 991 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 993 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 881 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1020 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 889 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 961 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 867 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 973 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1004 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 865 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 850 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 941 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 911 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 976 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 991 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 965 B

Some files were not shown because too many files have changed in this diff Show More