OldBlueWater/BlueWater/Assets/Doozy/Runtime/Common/CategoryNameGroup.cs

300 lines
14 KiB
C#
Raw Normal View History

// Copyright (c) 2015 - 2023 Doozy Entertainment. All Rights Reserved.
// This code can only be used under the standard Unity Asset Store End User License Agreement
// A Copy of the EULA APPENDIX 1 is available at http://unity3d.com/company/legal/as_terms
using System;
using System.Collections.Generic;
using System.Linq;
using Doozy.Runtime.Common.Extensions;
using UnityEngine;
namespace Doozy.Runtime.Common
{
/// <summary>
/// Base class for Category Name databases
/// </summary>
/// <typeparam name="T"> Type of <see cref="CategoryNameItem"/> </typeparam>
[Serializable]
public class CategoryNameGroup<T> where T : CategoryNameItem, new()
{
/// <summary> Default string value for Category </summary>
public static string defaultCategory => CategoryNameItem.k_DefaultCategory;
/// <summary> Default string value for Name </summary>
public static string defaultName => CategoryNameItem.k_DefaultName;
[SerializeField] private List<T> Items;
/// <summary> List of all the items (entries) in the database </summary>
public List<T> items => Items ??= new List<T> { new T() };
/// <summary>
/// Check if the database is empty.
/// <para/> This also add an entry with the default category and name values (if it's missing)
/// </summary>
public bool isEmpty
{
get
{
if (ContainsCategory(defaultCategory))
return items.Count < 2;
items.Add((T)new CategoryNameItem(defaultCategory, defaultName));
CleanDatabase();
return items.Count < 2;
}
}
#region Category
/// <summary> Check if the database contains an entry for the given category value </summary>
/// <param name="category"> Category value </param>
/// <returns> True if there is an item with the given category in the database, otherwise it returns false </returns>
public bool ContainsCategory(string category) =>
items.Any(data => data.category.Equals(CleanString(category)));
/// <summary> Check if the given category value can be added as an entry in the database </summary>
/// <param name="category"> Category value </param>
/// <returns> Operation result (True or False) and a success or failure reason message </returns>
public (bool, string) CanAddCategory(string category)
{
category = CleanString(category);
return category.IsNullOrEmpty()
? (false, $"Invalid '{nameof(category)}'. It cannot be null or empty or contain special characters")
: ContainsCategory(category)
? (false, $"'{category}' already exists")
: (true, $"Can add the '{category}' category");
}
/// <summary> Add a new item to the database with the given category value and the default name value </summary>
/// <param name="category"> Category value </param>
/// <returns> True if the operation was successful and false otherwise </returns>
public bool AddCategory(string category)
{
bool canAddCategory;
(canAddCategory, _) = CanAddCategory(category);
if (!canAddCategory) return false;
items.Add((T)new CategoryNameItem(category));
CleanDatabase();
return true;
}
/// <summary> Check if the given category name can be renamed to the new category name. </summary>
/// <param name="oldCategory"> Old category name </param>
/// <param name="newCategory"> New category value </param>
/// <returns> Operation result (True or False) and a success or failure reason message </returns>
public (bool, string) CanRenameCategory(string oldCategory, string newCategory)
{
oldCategory = CleanString(oldCategory);
newCategory = CleanString(newCategory);
return oldCategory.IsNullOrEmpty()
? (false, $"Invalid '{nameof(oldCategory)}'. It cannot be null or empty or contain special characters")
: !ContainsCategory(oldCategory)
? (false, $"'{oldCategory}' does not exist")
: newCategory.IsNullOrEmpty()
? (false, $"Invalid '{nameof(newCategory)}'. It cannot be null or empty or contain special characters")
: oldCategory.Equals(newCategory)
? (false, $"The new category '{newCategory}' is the same as the old category '{oldCategory}'")
: (true, $"Can rename the '{oldCategory}' category to '{newCategory}'");
}
/// <summary> Rename the given category value to the new category value </summary>
/// <param name="oldCategory"> Old category value </param>
/// <param name="newCategory"> New category value </param>
/// <returns> True if the operation was successful and false otherwise </returns>
public bool RenameCategory(string oldCategory, string newCategory)
{
bool canAddCategory;
(canAddCategory, _) = CanRenameCategory(oldCategory, newCategory);
if (!canAddCategory) return false;
oldCategory = CleanString(oldCategory);
newCategory = CleanString(newCategory);
var categoryItems = items.Where(data => data.category.Equals(oldCategory)).ToList();
foreach (T item in categoryItems)
item.SetCategory(newCategory);
CleanDatabase();
return true;
}
/// <summary> Check if the given category value can be removed from the database </summary>
/// <param name="category"> Category value </param>
/// <returns> Operation result (True or False) and a success or failure reason message </returns>
public (bool, string) CanRemoveCategory(string category) =>
category.Equals(defaultCategory)
? (false, $"Cannot remove the '{category}' category")
: !ContainsCategory(category)
? (false, $"The '{category}' category does not exist")
: (true, $"Can remove the '{category}' category");
/// <summary> Remove all the items from the database with the given category value </summary>
/// <param name="category"> Category value </param>
/// <returns> True if the operation was successful and false otherwise </returns>
public bool RemoveCategory(string category)
{
bool canRemoveCategory;
(canRemoveCategory, _) = CanRemoveCategory(category);
if (!canRemoveCategory) return false;
for (int i = items.Count - 1; i >= 0; i--)
{
if (items[i].category.Equals(category))
items.RemoveAt(i);
}
return true;
}
/// <summary> Get all the category names, sorted alphabetically </summary>
public IEnumerable<string> GetCategories()
{
CleanDatabase();
var set = new HashSet<string>();
// set.Add(defaultCategory); //add default
foreach (T data in items)
set.Add(data.category);
return set;
}
#endregion
#region Name
/// <summary> Check if the database contains an entry for the given category and name values </summary>
/// <param name="category"> Category value </param>
/// <param name="name"> Name value </param>
/// <returns> True if an entry was found and false otherwise </returns>
public bool ContainsName(string category, string name) =>
items.Any(data => data.category.Equals(CleanString(category)) & data.name.Equals(CleanString(name)));
/// <summary>
/// Check if an entry with the given category and name values can be added as an entry in the database
/// </summary>
/// <param name="category"> Category value </param>
/// <param name="name"> Name value </param>
/// <returns> Operation result (True or False) and a success or failure reason message </returns>
public (bool, string) CanAddName(string category, string name)
{
category = CleanString(category);
name = CleanString(name);
return category.IsNullOrEmpty()
? (false, $"Invalid '{nameof(category)}'. It cannot be null or empty or contain special characters")
: category.Equals(defaultCategory)
? (false, $"Cannot add anything to the '{category}' category")
: name.IsNullOrEmpty()
? (false, $"Invalid '{nameof(name)}'. It cannot be null or empty or contain special characters")
: ContainsName(category, name)
? (false, $"The '{name}' name already exists in the '{category}' category")
: (true, $"Can add the '{name}' name to the '{category}' category");
}
/// <summary> Add a new item to the database with the given category and name values </summary>
/// <param name="category"> Category value </param>
/// <param name="name"> Name value </param>
/// <returns> True if the operation was successful and false otherwise </returns>
public bool AddName(string category, string name)
{
bool canAddName;
(canAddName, _) = CanAddName(category, name);
if (!canAddName) return false;
items.Add((T)new CategoryNameItem(category, name));
CleanDatabase();
return true;
}
/// <summary> Check if the entry with the given category and name values can be removed from the database </summary>
/// <param name="category"> Category value </param>
/// <param name="name"> Name value </param>
/// <returns> Operation result (True or False) and a success or failure reason message </returns>
public (bool, string) CanRemoveName(string category, string name) =>
category.Equals(defaultCategory)
? (false, $"Cannot remove anything from the '{category}' category")
: name.Equals(defaultName)
? (false, $"Cannot remove '{name}'")
: !ContainsName(category, name)
? (false, $"The name '{name}' was not found in the '{category}' category")
: (true, $"Can remove the '{name}' from the '{category}' category");
/// <summary> Remove the database entry with the given category and name value </summary>
/// <param name="category"> Category value </param>
/// <param name="name"> Name value </param>
/// <returns> True if the operation was successful and false otherwise </returns>
public bool RemoveName(string category, string name)
{
bool canRemoveName;
(canRemoveName, _) = CanRemoveName(category, name);
if (!canRemoveName) return false;
for (int i = items.Count - 1; i >= 0; i--)
{
if (!items[i].category.Equals(category))
continue;
if (!items[i].name.Equals(name))
continue;
items.RemoveAt(i);
break;
}
return true;
}
/// <summary> Get data for the given category and name. Returns null if not found </summary>
/// <param name="category"> Target category </param>
/// <param name="name"> Target name </param>
/// <returns> The entry if found, null otherwise </returns>
public T Get(string category, string name) =>
items.Where(data => data.category.Equals(category)).FirstOrDefault(data => data.name.Equals(name));
/// <summary> Get all the names inside the given category </summary>
/// <param name="category"> Target category </param>
public IEnumerable<string> GetNames(string category)
{
CleanDatabase();
var set = new HashSet<string>();
//set.Add(defaultName); //add default name
foreach (T data in items.Where(data => data.category.Equals(category)))
set.Add(data.name);
return set;
}
#endregion
/// <summary> Clears the database and adds an entry with the default values </summary>
public void ClearDatabase()
{
items.Clear();
items.Add(new T()); //add the default values
}
/// <summary> Remove null or empty entries and sort the group by category and then by name </summary>
public void CleanDatabase()
{
//Remove null or empty entries - this should not be an issue due to the checks put in place when adding data to the group
for (int i = items.Count - 1; i >= 0; i--)
{
if (items[i] == null)
{
items.RemoveAt(i);
continue;
}
if (items[i].category.Trim().IsNullOrEmpty() | items[i].name.Trim().IsNullOrEmpty())
items.RemoveAt(i);
}
//Sort group
Items = items
.OrderBy(data => data.category)
.ThenBy(data => data.name)
.ToList();
}
/// <summary> Cleans the string by removing any empty spaces (at the start of the string and/or the end of the string) </summary>
/// <param name="value"> Target value </param>
/// <param name="removeWhitespaces"> Remove all whitespaces from the target string </param>
/// <param name="removeSpecialCharacters"> Remove all special characters from the target string </param>
/// <returns> The cleaned string </returns>
public static string CleanString(string value, bool removeWhitespaces = true, bool removeSpecialCharacters = true) =>
CategoryNameItem.CleanString(value, removeWhitespaces, removeSpecialCharacters);
}
}