I did little bit of exercise for tree structure data, since I am always struggling with it.

Example I took from my family tree. My grandfathers name was "Stanko" (same as me btw), he had three kids: my fathers name "Velimir", "Svetlana" and "Julka"
My father "Velimir" also had three kids: "Anamaria", "Stanko" and "Nikola"
His sister "Svetlana" had two kids: "Dragan" and "Dragana"
Dragan had one kid "Sanja" and "Dragana" two kids "Jovana" and "Aleksa"
Structure in string looks like this:

```"Stanko|Velimir|Anamaria"
"Stanko|Velimir|Stanko"
"Stanko|Velimir|Nikola"
"Stanko|Velimir|Anamaria|Tatjana"
"Stanko|Svetlana|Dragan"
"Stanko|Svetlana|Dragana"
"Stanko|Julka"
"Stanko|Svetlana|Dragan|Sanja"
"Stanko|Svetlana|Dragana|Jovana"
"Stanko|Svetlana|Dragana|Aleksa"
```
Main code:
```using System.Collections.Generic;

namespace TreeExample
{
class Program
{

static void Main(string[] args)
{
List<string> treeDescriptions = new List<string> { "Stanko|Velimir|Anamaria" };

TreeMethods geni = new TreeMethods();
TreeStructure geniStructure;

geniStructure = geni.CreateStructure(treeDescriptions);

}
}
}
```
Class:
```using System;
using System.Collections.Generic;

namespace TreeExample
{
class TreeStructure
{
public string Name { get; set; }
public List<TreeStructure> Children;
}

class TreeMethods
{
private TreeStructure CreateTree(string structure, TreeStructure parentTree)
{
if (string.IsNullOrWhiteSpace(structure))
{
return null;
}
else
{
string[] levels = structure.Split('|');
if (levels.Length > 1)
structure = structure.Substring(levels[0].Length + 1, structure.Length - levels[0].Length - 1);
else
structure = string.Empty;

if (parentTree is null)
{
parentTree = new TreeStructure();
parentTree.Name = levels[0];

if (!string.IsNullOrWhiteSpace(structure))
{
parentTree.Children = new List<TreeStructure>();
}
}
else if (parentTree.Children is null)
{
if (!string.IsNullOrWhiteSpace(structure))
{
parentTree.Children = new List<TreeStructure>();
}
}
else
{
bool found = false;
foreach (TreeStructure child in parentTree.Children)
{
string[] levelsChildren = structure.Split('|');

if (!(child is null))
{
if (string.Equals(child.Name, levelsChildren[0], StringComparison.InvariantCultureIgnoreCase))
{
CreateTree(structure, child);
}
}
}

foreach (TreeStructure child in parentTree.Children)
{
string[] levelsChildren = structure.Split('|');
if (!(child is null))
{
found = string.Equals(child.Name, levelsChildren[0], StringComparison.InvariantCultureIgnoreCase);
if (found)
{
break;
}
}
}

if (!found && !string.IsNullOrWhiteSpace(structure))
{
}

}
}

//there are no more leafs, go out
return parentTree;
}

public TreeStructure CreateStructure(List<string> structures)
{
TreeStructure treeStructure = null;

foreach (string structure in structures)
{
int level = 0;
string[] rootChildren = structure.Split('|');

treeStructure = CreateTree(structure, treeStructure);
}

return treeStructure;
}

}
}
```

Here I've already explained how to create custom section in App.config, but now I need more complicated stuff, I need to have more attributes then just key / value pair.

Here is the example:

```using System;
using System.Collections.Specialized;
using System.Configuration;

namespace CustomConfig
{
class Program
{
static void Main(string[] args)
{
string homePage = ConfigurationManager.AppSettings.Get("homePage");

{
}

Console.WriteLine("Press any key...");
}
}

public class MilosevBlogCategoriesElement : ConfigurationElement
{
[ConfigurationProperty("BlogCategory", IsKey = true, IsRequired = true)]
public string BlogCategory
{
get
{
return (string)base["BlogCategory"];
}
set
{
base["BlogCategory"] = value;
}
}
}

public class MilosevBlogCategoriesElementCollection : ConfigurationElementCollection
{
public MilosevBlogCategoriesElement this[int index]
{
get
{

return (MilosevBlogCategoriesElement)BaseGet(index);
}
set
{
if (BaseGet(index) != null)
BaseRemoveAt(index);

}
}

protected override ConfigurationElement CreateNewElement()
{
return new MilosevBlogCategoriesElement();
}

protected override object GetElementKey(ConfigurationElement element)
{
return ((MilosevBlogCategoriesElement)element).BlogCategory;
}
}

public class MilosevBlogConfig : ConfigurationSection
{
[ConfigurationProperty("categories")]
[ConfigurationCollection(typeof(MilosevBlogCategoriesElementCollection))]
{
get
{
return (MilosevBlogCategoriesElementCollection)this["categories"];
}
}
}
}
```
App.config should look like this:
```<?xml version="1.0" encoding="utf-8" ?>
<configuration>

<configSections>
<section name="milosev.com" type="CustomConfig.MilosevBlogConfig, CustomConfig"></section>
</configSections>

<milosev.com>
<categories>
</categories>
</milosev.com>

<appSettings>
</appSettings>

<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
</configuration>
```
POI in App.config:
```  <configSections>
<section name="milosev.com" type="CustomConfig.MilosevBlogConfig, CustomConfig"></section>
</configSections>
```
Where MilosevBlogConfig looks like:
```public class MilosevBlogConfig : ConfigurationSection
{
[ConfigurationProperty("categories")]
[ConfigurationCollection(typeof(MilosevBlogCategoriesElementCollection))]
{
get
{
return (MilosevBlogCategoriesElementCollection)this["categories"];
}
}
}
```
Interesting (and fast) way to fill the gap between numbers:

```static void Main(string[] args)
{
int[] gapNumbers = new int[] { 1, 3, 4, 7, 8, 10 };

foreach (int number in FillTheGap(gapNumbers))
{
Console.WriteLine(number);
}

}

private static IEnumerable<int> FillTheGap(int[] gapNumbers)
{
int prevNumber = 1;

foreach (int number in gapNumbers)
{
if (prevNumber == number)
{
yield return number;
}
else
{
for (; prevNumber < number; prevNumber++)
{
yield return prevNumber;
}
yield return number;
}
prevNumber++;
}
}
```

POI:

```foreach (int number in FillTheGap(gapNumbers))
```
Recently I had to automatically resize images, but I ran into problem that some images were rotated. Problem was the EXIF data on some of the images was altering the orientation of the images. As explained here. So here is my method for image resizing:
```    public void ResizeImage(string originalFilename, string saveTo,
int canvasWidth, int canvasHeight)
{
try
{
Image image = Image.FromFile(originalFilename);

Image thumbnail = new Bitmap(canvasWidth, canvasHeight);
Graphics graphic = Graphics.FromImage(thumbnail);

graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphic.SmoothingMode = SmoothingMode.HighQuality;
graphic.PixelOffsetMode = PixelOffsetMode.HighQuality;
graphic.CompositingQuality = CompositingQuality.HighQuality;

int originalWidth = image.Width;
int originalHeight = image.Height;

double ratioX = canvasWidth / (double)originalWidth;
double ratioY = canvasHeight / (double)originalHeight;

double ratio = ratioX < ratioY ? ratioX : ratioY;

int newHeight = Convert.ToInt32(originalHeight * ratio);
int newWidth = Convert.ToInt32(originalWidth * ratio);

int posX = Convert.ToInt32((canvasWidth - (originalWidth * ratio)) / 2);
int posY = Convert.ToInt32((canvasHeight - (originalHeight * ratio)) / 2);

graphic.DrawImage(image, posX, posY, newWidth, newHeight);

ImageCodecInfo[] info = ImageCodecInfo.GetImageEncoders();
EncoderParameters encoderParameters;
encoderParameters = new EncoderParameters(1);
encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality,
100L);

int OrientationKey = 0x0112;
const int NotSpecified = 0;
const int NormalOrientation = 1;
const int MirrorHorizontal = 2;
const int UpsideDown = 3;
const int MirrorVertical = 4;
const int MirrorHorizontalAndRotateRight = 5;
const int RotateLeft = 6;
const int MirorHorizontalAndRotateLeft = 7;
const int RotateRight = 8;

if (image.PropertyIdList.Contains(OrientationKey))
{
if (image.PropertyIdList.Contains(OrientationKey))
{
var orientation = (int)image.GetPropertyItem(OrientationKey).Value[0];
switch (orientation)
{
case NotSpecified: // Assume it is good.
case NormalOrientation:
// No rotation required.
break;
case MirrorHorizontal:
thumbnail.RotateFlip(RotateFlipType.RotateNoneFlipX);
break;
case UpsideDown:
thumbnail.RotateFlip(RotateFlipType.Rotate180FlipNone);
break;
case MirrorVertical:
thumbnail.RotateFlip(RotateFlipType.Rotate180FlipX);
break;
case MirrorHorizontalAndRotateRight:
thumbnail.RotateFlip(RotateFlipType.Rotate90FlipX);
break;
case RotateLeft:
thumbnail.RotateFlip(RotateFlipType.Rotate90FlipNone);
break;
case MirorHorizontalAndRotateLeft:
thumbnail.RotateFlip(RotateFlipType.Rotate270FlipX);
break;
case RotateRight:
thumbnail.RotateFlip(RotateFlipType.Rotate270FlipNone);
break;
default:
throw new NotImplementedException("An orientation of " + orientation + " isn't implemented.");
}
}
}

//thumbnail.RotateFlip(RotateFlipType.Rotate90FlipNone);
thumbnail.Save(saveTo, info[1], encoderParameters);
Debug.WriteLine(\$"Thumbnail from file: {originalFilename} created in {saveTo}");
}
catch (Exception e)
{
Debug.WriteLine(\$"Error creating thumbnail: {e.Message}");
}
}
```
POI:
```int OrientationKey = 0x0112;
const int NotSpecified = 0;
const int NormalOrientation = 1;
const int MirrorHorizontal = 2;
const int UpsideDown = 3;
const int MirrorVertical = 4;
const int MirrorHorizontalAndRotateRight = 5;
const int RotateLeft = 6;
const int MirorHorizontalAndRotateLeft = 7;
const int RotateRight = 8;

if (image.PropertyIdList.Contains(OrientationKey))
{
if (image.PropertyIdList.Contains(OrientationKey))
{
var orientation = (int)image.GetPropertyItem(OrientationKey).Value[0];
switch (orientation)
{
case NotSpecified: // Assume it is good.
case NormalOrientation:
// No rotation required.
break;
case MirrorHorizontal:
thumbnail.RotateFlip(RotateFlipType.RotateNoneFlipX);
break;
case UpsideDown:
thumbnail.RotateFlip(RotateFlipType.Rotate180FlipNone);
break;
case MirrorVertical:
thumbnail.RotateFlip(RotateFlipType.Rotate180FlipX);
break;
case MirrorHorizontalAndRotateRight:
thumbnail.RotateFlip(RotateFlipType.Rotate90FlipX);
break;
case RotateLeft:
thumbnail.RotateFlip(RotateFlipType.Rotate90FlipNone);
break;
case MirorHorizontalAndRotateLeft:
thumbnail.RotateFlip(RotateFlipType.Rotate270FlipX);
break;
case RotateRight:
thumbnail.RotateFlip(RotateFlipType.Rotate270FlipNone);
break;
default:
throw new NotImplementedException("An orientation of " + orientation + " isn't implemented.");
}
}
}
```
With this code I was checking if image has to be rotated. Example application (at this moment still under development), you can see on my GitHub.