Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Drawing;
- using System.IO;
- using System.Drawing.Drawing2D;
- ////// Example Usage:
- ////// static void Main(string[] args)
- ////// {
- ////// string[] TestData = {
- ////// ",0,100,0,10,1,50,1,50",
- ////// ",0,100,0,20,1,60,1,50",
- ////// ",0,100,0,30,1,70,1,50",
- ////// ",0,100,0,40,1,80,1,50",
- ////// ",0,100,0,50,1,90,1,50",
- ////// ",0,100,0,60,1,100,1,50",
- ////// ",0,100,0,70,1,50,1,50",
- ////// ",0,100,0,80,1,60,1,50",
- ////// ",0,100,0,90,1,70,1,50",
- ////// ",0,100,0,10,1,80,1,50",
- ////// ",0,100,0,20,1,90,1,50",
- ////// ",0,100,0,30,1,100,1,50",
- ////// ",0,100,0,40,1,50,1,50",
- ////// ",0,100,0,50,1,60,1,50",
- ////// ",0,100,0,60,1,70,1,50",
- ////// ",0,100,0,70,1,80,1,50",
- ////// ",0,100,0,80,1,90,1,50",
- ////// ",0,100,0,90,1,100,1,50",
- ////// };
- //////
- ////// GraphBuilderArgs gbargs = new GraphBuilderArgs()
- ////// {
- ////// //Data = CSVParser.ReadArray(TestData),
- ////// Data = CSVParser.ReadFile("C:\\Users\\user\\Documents\\output.csv"),
- ////// Width = 1920,
- ////// Height = 1080,
- ////// };
- //////
- ////// GraphBuilder.Build(gbargs).Save("C:\\Users\\user\\Documents\\data.png");
- ////// }
- namespace CashGraph
- {
- public struct GraphBuilderArgs
- {
- public int Height { get; set; }
- public int Width { get; set; }
- public List<Bars> Data { get; set; }
- }
- static class GraphBuilder
- {
- public static Bitmap Build(GraphBuilderArgs args)
- {
- List<Bars> Data = args.Data;
- //Determine the max value;
- int Income = Largest(Data, 0);
- int Expense = Largest(Data, 1);
- //Some constants
- int Margin = 5;
- int EqualsBarWidth = 2;
- float YScale = (float)(args.Height - (Margin * 2)) / (float)(Income + Expense + EqualsBarWidth + 0.0f) * 0.99f;
- int XScale = (int)Math.Floor((double)((args.Width - (Margin * 2) + 0.0) / Data.Count + 0.0));
- if (XScale < 1) Console.Write("Warning: XSCALE is less than 1, is your Width too small?");
- //We are just gonna resize it to make it work perfectly;
- args.Width = (Margin) + (Data.Count * XScale);
- int EqualsBarLevel = (int)(Income * YScale) + Margin;
- Bitmap Image = new Bitmap(args.Width, args.Height);
- Graphics g = Graphics.FromImage(Image);
- //g.SmoothingMode = SmoothingMode.AntiAlias;
- g.InterpolationMode = InterpolationMode.HighQualityBicubic;
- g.PixelOffsetMode = PixelOffsetMode.HighQuality;
- int i, j, offset, barOffset, monthOffset = 0;
- DateTime currentMonth = DateTime.MinValue;
- for (i = 0; i < Data.Count; i++)
- {
- offset = (i * XScale) + Margin + (monthOffset * XScale);
- barOffset = EqualsBarLevel - EqualsBarWidth;
- for (j = 0; j < Data[i][0].Count; j++)
- {
- using (var pen = new Pen(GetIncomeColor(j), XScale))
- g.DrawLine(pen,
- offset, barOffset,
- offset, barOffset - (Data[i][0][j] * YScale));
- barOffset = (int)(barOffset - (Data[i][0][j] * YScale)) + 1;
- }
- barOffset = EqualsBarLevel;
- for (j = 0; j < Data[i][0].Count; j++)
- {
- using (var pen = new Pen(GetExpenseColor(j), XScale))
- g.DrawLine(pen,
- offset, barOffset,
- offset, barOffset + (Data[i][1][j] * YScale));
- barOffset = (int)(barOffset + (Data[i][1][j] * YScale)) - 1;
- }
- if (i == 0)
- currentMonth = new DateTime(Data[i].Date.Year, Data[i].Date.Month, 1);
- if (currentMonth != new DateTime(Data[i].Date.Year, Data[i].Date.Month, 1))
- currentMonth = new DateTime(Data[i].Date.Year, Data[i].Date.Month, 1);
- }
- for (i = 0; i < Data.Count; i++)
- {
- offset = (i * XScale) + Margin + (monthOffset * XScale);
- if (i == 0)
- currentMonth = new DateTime(Data[i].Date.Year, Data[i].Date.Month, 1);
- if (currentMonth != new DateTime(Data[i].Date.Year, Data[i].Date.Month, 1))
- {
- barOffset = EqualsBarLevel - EqualsBarWidth;
- //monthOffset++;
- currentMonth = new DateTime(Data[i].Date.Year, Data[i].Date.Month, 1);
- using (var pen = new Pen(Color.Black, EqualsBarWidth))
- g.DrawLine(pen,
- (i * XScale) + Margin, barOffset - (Data[i].Sum(0) * YScale),
- (i * XScale) + Margin, barOffset + (Data[i].Sum(1) * YScale));
- g.DrawString(currentMonth.ToString("MMM"), new Font("Tahoma", 20), Brushes.Black, offset + 10, barOffset + 10);
- }
- }
- using (var pen = new Pen(Color.Black, EqualsBarWidth))
- {
- g.FillRectangle(Brushes.Blue, 10, 10, 30, 30);
- g.DrawRectangle(pen, 10, 10, 30, 30);
- g.DrawString("Checking", new Font("Tahoma", 20), Brushes.Black, 50, 10);
- g.FillRectangle(Brushes.Green, 10, 50, 30, 30);
- g.DrawRectangle(pen, 10, 50, 30, 30);
- g.DrawString("Savings", new Font("Tahoma", 20), Brushes.Black, 50, 50);
- g.FillRectangle(Brushes.Red, 10, 90, 30, 30);
- g.DrawRectangle(pen, 10, 90, 30, 30);
- g.DrawString("Student Loans", new Font("Tahoma", 20), Brushes.Black, 50, 90);
- g.FillRectangle(Brushes.Orange, 10, 130, 30, 30);
- g.DrawRectangle(pen, 10, 130, 30, 30);
- g.DrawString("Credit Cards", new Font("Tahoma", 20), Brushes.Black, 50, 130);
- }
- using (var pen = new Pen(Color.Black, EqualsBarWidth))
- g.DrawLine(pen,
- Margin-2, EqualsBarLevel-1,
- (Data.Count * XScale) + Margin-2, EqualsBarLevel-1);
- return Image;
- }
- private static int GetMonthCount(List<Bars> Data)
- {
- List<DateTime> seenMonths = new List<DateTime>();
- Data.ForEach((Bars data) => {
- var now = DateTime.Now;
- if (!seenMonths.Contains(new DateTime(now.Year, now.Month, 1))) seenMonths.Add(new DateTime(now.Year, now.Month, 1));
- });
- return seenMonths.Count;
- }
- private static int Largest(List<Bars> Data, int Index)
- {
- int Highest = 0;
- Data.ForEach((Bars data) =>
- {
- int sum = data.Sum(Index);
- if (sum > Highest) Highest = sum;
- });
- return Highest;
- }
- public static Color GetExpenseColor(int id)
- {
- Color[] colors = { Color.Red, Color.Orange, Color.OrangeRed };
- if (id < 0 || id >= colors.Length) id = colors.Length - 1;
- return colors[id];
- }
- public static Color GetIncomeColor(int id)
- {
- Color[] colors = { Color.Green, Color.Blue, Color.Turquoise };
- if (id < 0 || id >= colors.Length) id = colors.Length - 1;
- return colors[id];
- }
- }
- public class Bars
- {
- int[][] _data;
- public List<int> this[int index] { get { return new List<int>(_data[index]); } }
- public DateTime Date { get; set; }
- public Bars(int[][] data, DateTime date)
- {
- Date = date;
- _data = data;
- }
- public int Sum(int index)
- {
- return _data[index].Sum();
- }
- }
- public class CSVParser
- {
- public static List<Bars> ReadFile(string filename)
- {
- return ReadArray(File.ReadAllLines(filename));
- }
- public static List<Bars> ReadArray(string[] Array)
- {
- List<string> lines = new List<string>(Array);
- List<Bars> Data = new List<Bars>(lines.Count);
- lines.ForEach((string s) =>
- {
- List<int> income = new List<int>();
- List<int> expense = new List<int>();
- string[] parsed = s.ToLower().Split(',');
- if (parsed[0] == "date") return; //Skip over a header
- //This could be ugly when they don't put a date/time parsable element there but /shrug
- DateTime date = parsed[0].Length > 0 ? DateTime.Parse(parsed[0]) : DateTime.MinValue;
- for (int i = 1; i < parsed.Length; i += 2)
- {
- //Also could be ugly, yay exceptions
- int Type = GetType(parsed[i]);
- if (Type == 0) income.Add(int.Parse(parsed[i + 1]));
- if (Type == 1) expense.Add(int.Parse(parsed[i + 1]));
- }
- Data.Add(new Bars(new int[][]{ income.ToArray(), expense.ToArray() }, date));
- });
- return Data;
- }
- private static int GetType(string s)
- {
- if (s == "income" || s == "0") return 0;
- if (s == "expense" || s == "1") return 1;
- throw new Exception(String.Format("Input is not [Income|Expense|0|1]: {0}", s));
- }
- }
- }
Add Comment
Please, Sign In to add comment