Nu har det tillkommit en source med data för demo
This commit is contained in:
@ -5,4 +5,19 @@
|
|||||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Remove="SearchByAuthor.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.NETCore.App" Version="2.2.8" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="books.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
52
Books.ConsoleApp/Books.cs
Normal file
52
Books.ConsoleApp/Books.cs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Books.ConsoleApp
|
||||||
|
{
|
||||||
|
public class BooksCollection
|
||||||
|
{
|
||||||
|
public Book[] Books { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Book
|
||||||
|
{
|
||||||
|
public string[] categories;
|
||||||
|
public string author { get; set; }
|
||||||
|
public string country { get; set; }
|
||||||
|
public string imageLink { get; set; }
|
||||||
|
public string language { get; set; }
|
||||||
|
public string link { get; set; }
|
||||||
|
public int pages { get; set; }
|
||||||
|
public string title { get; set; }
|
||||||
|
public int year { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IBooksSource
|
||||||
|
{
|
||||||
|
Book[] Read();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BooksJsonSource : IBooksSource
|
||||||
|
{
|
||||||
|
private string booksJsonFile;
|
||||||
|
|
||||||
|
public BooksJsonSource(string booksFile = "books.json")
|
||||||
|
{
|
||||||
|
booksJsonFile = booksFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Book[] Read()
|
||||||
|
{
|
||||||
|
var rawJsonBooks = File.ReadAllTextAsync(booksJsonFile)
|
||||||
|
// this (the .Result)is blocking the "UI"/"Main" thread - done for simplicity
|
||||||
|
// but utterly and very and fundamentaly wrong for production apps!
|
||||||
|
.Result;
|
||||||
|
|
||||||
|
return JsonConvert.DeserializeObject<Book[]>(rawJsonBooks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
80
Books.ConsoleApp/Output.cs
Normal file
80
Books.ConsoleApp/Output.cs
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Books.ConsoleApp
|
||||||
|
{
|
||||||
|
public class Output
|
||||||
|
{
|
||||||
|
private static List<BooksByAuthor> BooksByAuthorCatalog;
|
||||||
|
|
||||||
|
public static void BooksByAuthor(IEnumerable<Book> books)
|
||||||
|
{
|
||||||
|
BooksByAuthorCatalog = new List<BooksByAuthor>();
|
||||||
|
|
||||||
|
foreach(var book in books)
|
||||||
|
{
|
||||||
|
if (AuthorIsAlreadyCataloged(book.author))
|
||||||
|
{
|
||||||
|
// there are some(1 or more) books by this author already found and catalogued
|
||||||
|
var authorAndBooks = LocateAuthorAlreadyCataloged(book.author);
|
||||||
|
authorAndBooks.Books.Add(book);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CatalogueNewAuthor(book);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// now we have an list that has all the authors catalogued
|
||||||
|
OutputBooksByAuthor();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool AuthorIsAlreadyCataloged(string author)
|
||||||
|
{
|
||||||
|
return BooksByAuthorCatalog.Any(ba => ba.Author == author);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BooksByAuthor LocateAuthorAlreadyCataloged(string author)
|
||||||
|
{
|
||||||
|
return BooksByAuthorCatalog.First(ba => ba.Author == author);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CatalogueNewAuthor(Book b)
|
||||||
|
{
|
||||||
|
// there are NONE books by this author already found and cataloged
|
||||||
|
|
||||||
|
var newBooksList = new List<Book> { b };
|
||||||
|
var authorAndBooks = new BooksByAuthor(b.author, newBooksList);
|
||||||
|
|
||||||
|
BooksByAuthorCatalog.Add(authorAndBooks);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static void OutputBooksByAuthor()
|
||||||
|
{
|
||||||
|
foreach(var ba in BooksByAuthorCatalog)
|
||||||
|
{
|
||||||
|
System.Console.Write("Author: {0,-28} Books: ", ba.Author);
|
||||||
|
foreach (var book in ba.Books)
|
||||||
|
{
|
||||||
|
System.Console.Write(book.title + ", ");
|
||||||
|
}
|
||||||
|
System.Console.Write(Environment.NewLine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BooksByAuthor
|
||||||
|
{
|
||||||
|
public readonly string Author;
|
||||||
|
public readonly List<Book> Books;
|
||||||
|
|
||||||
|
public BooksByAuthor(string author, List<Book> books)
|
||||||
|
{
|
||||||
|
Author = author;
|
||||||
|
Books = books;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,107 +2,70 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.Contracts;
|
using System.Diagnostics.Contracts;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using Books.ConsoleApp;
|
||||||
|
|
||||||
namespace Books.Console
|
namespace Books.Console
|
||||||
{
|
{
|
||||||
class Program
|
class Program
|
||||||
{
|
{
|
||||||
List<BooksByAuthor> BooksByAuthorCatalogue = null;
|
private static IBooksSource BooksSource = new BooksJsonSource();
|
||||||
|
private static List<BooksByAuthor> BooksByAuthorCatalog = null;
|
||||||
static void Main(string[] args)
|
static void Main(string[] args)
|
||||||
{
|
{
|
||||||
IEnumerable<Book> books = BookSource.Read();
|
IEnumerable<Book> books = BooksSource.Read();
|
||||||
BooksByAuthorCatalogue = new List<BooksByAuthor>();
|
BooksByAuthorCatalog = new List<BooksByAuthor>();
|
||||||
|
|
||||||
foreach (var book in books)
|
|
||||||
{
|
|
||||||
if (AuthorIsAlreadyCataloged(book.author))
|
|
||||||
{
|
|
||||||
// there are some(1 or more) books by this author already found and catalogued
|
|
||||||
var authorCatalogueIndex = LocateAuthorAlreadyCataloged(book.author);
|
|
||||||
|
|
||||||
var existingBooks = BooksByAuthorCatalogue[authorCatalogIndex].Books;
|
while (true)
|
||||||
existingBooks.Add(book);
|
{
|
||||||
|
System.Console.WriteLine("\nActions available:");
|
||||||
|
System.Console.WriteLine("1 - Output all books by author (Section 2)");
|
||||||
|
System.Console.WriteLine("2 - Search books by title (Section 3)");
|
||||||
|
System.Console.WriteLine("Any other key - Exit");
|
||||||
|
|
||||||
|
var key = System.Console.ReadKey();
|
||||||
|
switch (key.KeyChar)
|
||||||
|
{
|
||||||
|
case '1': Output.BooksByAuthor(BooksSource.Read()); break;
|
||||||
|
case '2': DoSearch(); break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void DoSearch()
|
||||||
|
{
|
||||||
|
var books = BooksSource.Read();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine("\nSearch by book title or a part of it. \n^^^^Type 'exit' to go back^^^^");
|
||||||
|
var searchTerm = System.Console.ReadLine();
|
||||||
|
if (searchTerm == "exit")
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(searchTerm))
|
||||||
|
{
|
||||||
|
var booksByAuthor = Search.ByTitle(books, searchTerm);
|
||||||
|
|
||||||
|
if (booksByAuthor.Count() == 0)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine($"No books found for '{searchTerm}'");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CatalogueNewAuthor(book);
|
foreach (var b in booksByAuthor)
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool AuthorIsAlreadyCataloged(string author)
|
|
||||||
{
|
{
|
||||||
var authorAlreadyCatalogued = false;
|
System.Console.WriteLine($"{b.author}: {b.title}");
|
||||||
|
}
|
||||||
// we'll iterate over the catalogue to find the author - if athors's already been cataloged
|
|
||||||
|
|
||||||
foreach (var entry in BooksByAuthorCatalogue)
|
|
||||||
{
|
|
||||||
if (entry.author == author)
|
|
||||||
{
|
|
||||||
authorAlreadyCatalogued = true;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return authorAlreadyCatalogued;
|
System.Console.WriteLine("----------------------");
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int LocateAuthorAlreadyCataloged(string author)
|
|
||||||
{
|
|
||||||
var authorCatalogIndex = 0;
|
|
||||||
|
|
||||||
// We'll iterate over the cataloge to find the author's index
|
|
||||||
for (int j = 0; j < BooksByAuthorCatalogue.Count; j++)
|
|
||||||
{
|
|
||||||
var entry = BooksByAuthorCatalogue[j];
|
|
||||||
if (entry.Author == author)
|
|
||||||
{
|
|
||||||
authorCatalogIndex = j;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CatalogueNewAuthor(Book b)
|
|
||||||
{
|
|
||||||
// there are NONE books by this author already found and cataloged
|
|
||||||
|
|
||||||
var newBookList = new List<Book> { b };
|
|
||||||
var authorAndBooks = new BooksByAuthor(b.Author, newBookList);
|
|
||||||
|
|
||||||
BooksByAuthorCatalogue.Add(authorAndBooks);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void OutputBooksByAuthor()
|
|
||||||
{
|
|
||||||
foreach (var ba in BooksByAuthorCatalogue)
|
|
||||||
{
|
|
||||||
System.Console.Write("Author: {0, -28} Books: ", ba.Author);
|
|
||||||
foreach (var book in ba.Books)
|
|
||||||
{
|
|
||||||
System.Console.Write(book.title + ", ");
|
|
||||||
}
|
|
||||||
System.Console.Write(Environment.NewLine);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public class BooksByAuthor
|
|
||||||
{
|
|
||||||
public readonly string Author;
|
|
||||||
public readonly List<Book> Books;
|
|
||||||
|
|
||||||
public BooksByAuthor(string author, List<Book> books)
|
|
||||||
{
|
|
||||||
Author = author;
|
|
||||||
Books = books;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@ using System.Data.SqlTypes;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Books.Console
|
namespace Books.ConsoleApp
|
||||||
{
|
{
|
||||||
public static class SearchByAuthor
|
public static class SearchByAuthor
|
||||||
{
|
{
|
||||||
@ -78,8 +78,8 @@ namespace Books.Console
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Book
|
//public class Book
|
||||||
{
|
//{
|
||||||
|
|
||||||
}
|
//}
|
||||||
}
|
}
|
||||||
|
|||||||
28
Books.ConsoleApp/SearchByTitle.cs
Normal file
28
Books.ConsoleApp/SearchByTitle.cs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Books.ConsoleApp
|
||||||
|
{
|
||||||
|
|
||||||
|
public class Search
|
||||||
|
{
|
||||||
|
public static IEnumerable<Book> ByTitle(IEnumerable<Book> books, string titlePartial)
|
||||||
|
{
|
||||||
|
var titlePartialLowercased = titlePartial.ToLower();
|
||||||
|
|
||||||
|
return books
|
||||||
|
.Where(b =>
|
||||||
|
{
|
||||||
|
var bookTitleLowercased = b.title.ToLower();
|
||||||
|
return bookTitleLowercased.Contains(titlePartialLowercased);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<Book> SuggestRandom(IEnumerable<Book> books, int count = 5)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1002
Books.ConsoleApp/books-raw.json
Normal file
1002
Books.ConsoleApp/books-raw.json
Normal file
File diff suppressed because it is too large
Load Diff
1687
Books.ConsoleApp/books.json
Normal file
1687
Books.ConsoleApp/books.json
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user