Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //reference System.dll, System.Drawing.dll, LEDmatrix.dll
- /* LICENSE
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License (GPL) as published by
- the Free Software Foundation; either version 2 of the License, or (at
- your option) any later version. The full text of versions 2 and 3 of
- the GPL can be found respectively in the files LICENSE-GPLV2 and
- LICENSE-GPLV3.
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
- Public License for more details.
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
- /*
- * Written by coynzer, https://bitcointalk.org/index.php?action=profile;u=153694
- *
- * Version 0.1
- *
- * I don't think I will do a lot of support for this code, either it works for you or it doesn't. No guarantees given whatsoever.
- * However, if you have any questions or problems you could try asking in the respective forum post and might get help:
- * https://bitcointalk.org/index.php?topic=310184.0
- *
- * This plug-in will turn your USB message board into a BTC exchange rater ticker. The ticker is using the
- * last price from Mt.Gox for the selected currency.
- *
- * If you want to add a new currency first the easiest way is to copy an existing block, e.g. that for USD starting with this line:
- * public class USD : LedProgramBase
- * The end of the block is the line with a single "}" on the same level as where the above line is. Create a copy that whole block
- * directly after it.
- * The part "USD" on this line is the name that will be shown in the selection box, e.g. if you call your currency "XYZ" it
- * will be shown as "BTCTicker.XYZ". Please note that you may not use spaces or special characters in this name.
- *
- * In the last step you have to tell the new ticker which exchange rate to fetch from Mt.Gox, e.g. in the code you
- * copied it is BTC to USD which is expressed in the concatenated string "BTCUSD" in the code below:
- * Ticker ticker = new Ticker("BTCUSD");
- * If you want to get the rate for BTC to XYZ instead you would replace that with "BTCXYZ". In the future it should also
- * be possible to use something as "BTCLTC". You can see a list of available tickers here;
- * https://bitbucket.org/nitrous/mtgox-api/overview#markdown-header-streamlist_public
- *
- * Now after you have done your changes you can save the file and click the "Reload" button in the USB LED Driver program
- * and your new ticker should be available from the drop-down list.
- */
- using System;
- using System.Diagnostics;
- using System.Drawing;
- using System.Globalization;
- using System.IO;
- using System.Net;
- using System.Net.Sockets;
- using System.Text.RegularExpressions;
- using LedMatrixComms;
- namespace BTCTicker
- {
- public class Ticker
- {
- #region Settings
- public static int RefreshInterval = 5000; // minimum refresh exchange interval in milliseconds
- public static int DrawInterval = 500; // animation draw interval in milliseconds
- static bool AnimationEnabled = true; // set to "false" if you want to disable animation when the exchange rate changes
- const string TickerBaseUrl = "https://data.mtgox.com/api/2/$CURRENCY$/money/ticker_fast"; // base Mt.Gox ticker URL with a $CURRENCY$ variable
- const string TickerRegexString = @"\""last\""\:\{\""value\""\:\""(?<VALUE>\d+\.\d+)\""\,"; // don't change this if you don't know what you are doing
- const int AnimationBaseY = -3; // don't change this if you don't know what you are doing
- #endregion Settings
- #region Private objects
- Font drawFont = new Font(FontFamily.GenericSansSerif, 9f, GraphicsUnit.Pixel);
- SolidBrush drawBrush = new SolidBrush(Color.Black);
- Regex tickerRegex = new Regex(TickerRegexString);
- string tickerUrl = "";
- WebClient webClient = new WebClient();
- string lastPriceString = " ";
- string priceString = "1";
- double lastPrice = 0;
- double price = 1;
- int animationPosition = 0;
- Stopwatch lastRefresh = new Stopwatch();
- #endregion Private objects
- public Ticker(string currency)
- {
- tickerUrl = TickerBaseUrl.Replace("$CURRENCY$", currency);
- }
- private void getCurrentPrice()
- {
- string errorString = "Err01";
- try
- {
- string jsonSring = webClient.DownloadString(tickerUrl);
- errorString = "Err02";
- Match regexMatch = tickerRegex.Match(jsonSring);
- errorString = "Err03";
- string regexValue = regexMatch.Groups["VALUE"].Value;
- errorString = "Err04";
- double priceValue = Convert.ToDouble(regexValue, CultureInfo.InvariantCulture);
- errorString = "Err05";
- int lenght = Math.Truncate(priceValue).ToString().Length;
- if (lenght > 4)
- {
- priceString = errorString;
- price = double.NaN;
- return;
- }
- errorString = "Err06";
- int fractionDigits = Math.Max(0, (4 - lenght));
- errorString = "Err07";
- double priceValueRounded = Math.Round(priceValue, fractionDigits);
- errorString = "Err08";
- priceString = priceValueRounded.ToString(CultureInfo.InvariantCulture);
- price = priceValueRounded;
- }
- catch
- {
- priceString = errorString;
- price = double.NaN;
- }
- // code for testing the animation (uncomment this and comment all lines above to use it)
- // Random random = new Random();
- // price = Convert.ToDouble(random.Next(90, 110));
- // priceString = price.ToString(CultureInfo.InvariantCulture);
- }
- public void DrawPrice(Graphics g)
- {
- if ((!lastRefresh.IsRunning) || (lastRefresh.ElapsedMilliseconds > RefreshInterval) && (animationPosition == 0))
- {
- getCurrentPrice();
- if (AnimationEnabled)
- {
- if (!double.IsNaN(price))
- {
- if (price > lastPrice)
- animationPosition = 1;
- else if (price < lastPrice)
- animationPosition = -1;
- else
- animationPosition = 0;
- }
- lastRefresh.Reset();
- lastRefresh.Start();
- }
- else
- {
- if (lastPriceString != priceString)
- {
- // clear the display
- g.Clear(Color.White);
- drawPriceText(g, priceString, AnimationBaseY);
- lastPriceString = priceString;
- lastPrice = price;
- }
- lastRefresh.Reset();
- lastRefresh.Start();
- return;
- }
- }
- if (animationPosition == 0)
- return;
- // clear the display
- g.Clear(Color.White);
- drawPriceText(g, lastPriceString, AnimationBaseY + animationPosition);
- if (animationPosition > 0)
- {
- drawPriceText(g, priceString, AnimationBaseY + animationPosition - 8);
- animationPosition++;
- }
- else if (animationPosition < 0)
- {
- drawPriceText(g, priceString, AnimationBaseY + animationPosition + 8);
- animationPosition--;
- }
- if (Math.Abs(animationPosition) == 9)
- {
- animationPosition = 0;
- lastPriceString = priceString;
- lastPrice = price;
- }
- }
- private void drawPriceText(Graphics g, string priceText, int yPos)
- {
- // if this an error message just draw it without using the spacing logics below
- int xPos = -2;
- if (priceText.StartsWith("Err"))
- {
- g.DrawString(priceText, drawFont, drawBrush, xPos, yPos);
- return;
- }
- // spacing logic starts here
- // the digit "4" is one pixel wider than all others - we will try use extra space from "." and "1" which are not as wide as others
- int pixelWidth = 0;
- for (int charIndex = 0; charIndex < priceText.Length; charIndex++)
- {
- if (charIndex > 0)
- pixelWidth++; // add leading pixel space
- switch (priceText[charIndex])
- {
- case '.':
- pixelWidth += 1;
- break;
- case '1':
- pixelWidth += 2;
- break;
- default:
- pixelWidth += 4;
- break;
- }
- }
- int pixelBuffer = 21 - pixelWidth; // calculate spare pixels we can use for extra space after the number 4, which is one pixel wider than all other numbers
- bool lastIs4 = (priceText[priceText.Length - 1] == '4');
- if (lastIs4) // if "4" is the last digit we MUST give it the extra pixel so reserve that in the buffer already
- pixelBuffer--;
- for (int charIndex = 0; charIndex < priceText.Length; charIndex++)
- {
- if (priceText[charIndex] == '1')
- xPos -= 1;
- if (priceText[charIndex] == '.')
- xPos -= 1;
- g.DrawString(priceText.Substring(charIndex, 1), drawFont, drawBrush, xPos, yPos);
- if (priceText[charIndex] == '.')
- xPos += 3;
- else if (priceText[charIndex] == '1')
- xPos += 4;
- else if ((priceText[charIndex] == '4') && (pixelBuffer > 0) && (charIndex < (priceText.Length - 1)))
- {
- // if this a "4" and we still got spare pixels in the buffer then use it here
- xPos += 6;
- pixelBuffer--;
- }
- else
- xPos += 5;
- if ((charIndex == (priceText.Length - 1)) && (lastIs4)) // if the following last character is a "4" add the extra pixel space we reserved
- xPos++;
- }
- }
- }
- #region Currency implementations
- public class USD : LedProgramBase
- {
- Ticker ticker = new Ticker("BTCUSD");
- public override int Speed()
- {
- return Ticker.DrawInterval;
- }
- public override void Setup(LedUsbDevice device)
- {
- }
- protected override void Update(Graphics g)
- {
- ticker.DrawPrice(g);
- }
- }
- public class EUR : LedProgramBase
- {
- Ticker ticker = new Ticker("BTCEUR");
- public override int Speed()
- {
- return Ticker.DrawInterval;
- }
- public override void Setup(LedUsbDevice device)
- {
- }
- protected override void Update(Graphics g)
- {
- ticker.DrawPrice(g);
- }
- }
- public class CAD : LedProgramBase
- {
- Ticker ticker = new Ticker("BTCCAD");
- public override int Speed()
- {
- return Ticker.DrawInterval;
- }
- public override void Setup(LedUsbDevice device)
- {
- }
- protected override void Update(Graphics g)
- {
- ticker.DrawPrice(g);
- }
- }
- public class GBP : LedProgramBase
- {
- Ticker ticker = new Ticker("BTCGBP");
- public override int Speed()
- {
- return Ticker.DrawInterval;
- }
- public override void Setup(LedUsbDevice device)
- {
- }
- protected override void Update(Graphics g)
- {
- ticker.DrawPrice(g);
- }
- }
- #endregion Currency implementations
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement