Advertisement
Guest User

coynzer.BTCTicker

a guest
Oct 13th, 2013
331
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 10.39 KB | None | 0 0
  1. //reference System.dll, System.Drawing.dll, LEDmatrix.dll
  2.  
  3. /* LICENSE
  4.  
  5. This program is free software; you can redistribute it and/or modify it
  6. under the terms of the GNU General Public License (GPL) as published by
  7. the Free Software Foundation; either version 2 of the License, or (at
  8. your option) any later version. The full text of versions 2 and 3 of
  9. the GPL can be found respectively in the files LICENSE-GPLV2 and
  10. LICENSE-GPLV3.
  11.  
  12. This program is distributed in the hope that it will be useful, but
  13. WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
  15. Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License along
  18. with this program; if not, write to the Free Software Foundation, Inc.,
  19. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  20. */
  21.  
  22. /*
  23.  * Written by coynzer, https://bitcointalk.org/index.php?action=profile;u=153694
  24.  *
  25.  * Version 0.1
  26.  *
  27.  * 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.
  28.  * However, if you have any questions or problems you could try asking in the respective forum post and might get help:
  29.  * https://bitcointalk.org/index.php?topic=310184.0
  30.  *
  31.  * This plug-in will turn your USB message board into a BTC exchange rater ticker. The ticker is using the
  32.  * last price from Mt.Gox for the selected currency.
  33.  *
  34.  * 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:
  35.  *   public class USD : LedProgramBase
  36.  * 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
  37.  * directly after it.
  38.  * 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
  39.  * will be shown as "BTCTicker.XYZ". Please note that you may not use spaces or special characters in this name.
  40.  *
  41.  * 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
  42.  * copied it is BTC to USD which is expressed in the concatenated string "BTCUSD" in the code below:
  43.  *   Ticker ticker = new Ticker("BTCUSD");
  44.  * If you want to get the rate for BTC to XYZ instead you would replace that with "BTCXYZ". In the future it should also
  45.  * be possible to use something as "BTCLTC". You can see a list of available tickers here;  
  46.  * https://bitbucket.org/nitrous/mtgox-api/overview#markdown-header-streamlist_public
  47.  *
  48.  * Now after you have done your changes you can save the file and click the "Reload" button in the USB LED Driver program
  49.  * and your new ticker should be available from the drop-down list.
  50.  */
  51.  
  52.  
  53. using System;
  54. using System.Diagnostics;
  55. using System.Drawing;
  56. using System.Globalization;
  57. using System.IO;
  58. using System.Net;
  59. using System.Net.Sockets;
  60. using System.Text.RegularExpressions;
  61. using LedMatrixComms;
  62.  
  63. namespace BTCTicker
  64. {
  65.    
  66.     public class Ticker
  67.     {
  68.         #region Settings
  69.         public static int RefreshInterval = 5000; // minimum refresh exchange interval in milliseconds
  70.         public static int DrawInterval = 500; // animation draw interval in milliseconds
  71.        
  72.         static bool AnimationEnabled = true; // set to "false" if you want to disable animation when the exchange rate changes
  73.         const string TickerBaseUrl = "https://data.mtgox.com/api/2/$CURRENCY$/money/ticker_fast"; // base Mt.Gox ticker URL with a $CURRENCY$ variable
  74.         const string TickerRegexString = @"\""last\""\:\{\""value\""\:\""(?<VALUE>\d+\.\d+)\""\,"; // don't change this if you don't know what you are doing
  75.         const int AnimationBaseY = -3; // don't change this if you don't know what you are doing
  76.         #endregion Settings
  77.        
  78.         #region Private objects
  79.         Font drawFont = new Font(FontFamily.GenericSansSerif, 9f, GraphicsUnit.Pixel);
  80.         SolidBrush drawBrush = new SolidBrush(Color.Black);
  81.         Regex tickerRegex = new Regex(TickerRegexString);
  82.         string tickerUrl = "";
  83.         WebClient webClient = new WebClient();
  84.         string lastPriceString = " ";
  85.         string priceString = "1";
  86.         double lastPrice = 0;
  87.         double price = 1;
  88.         int animationPosition = 0;
  89.         Stopwatch lastRefresh = new Stopwatch();
  90.         #endregion Private objects
  91.        
  92.         public Ticker(string currency)
  93.         {
  94.             tickerUrl = TickerBaseUrl.Replace("$CURRENCY$", currency);
  95.         }
  96.        
  97.         private void getCurrentPrice()
  98.         {
  99.             string errorString = "Err01";
  100.             try
  101.             {
  102.                 string jsonSring = webClient.DownloadString(tickerUrl);
  103.                 errorString = "Err02";
  104.                 Match regexMatch = tickerRegex.Match(jsonSring);
  105.                 errorString = "Err03";
  106.                 string regexValue = regexMatch.Groups["VALUE"].Value;
  107.                 errorString = "Err04";
  108.                 double priceValue = Convert.ToDouble(regexValue, CultureInfo.InvariantCulture);
  109.                 errorString = "Err05";
  110.                 int lenght = Math.Truncate(priceValue).ToString().Length;
  111.                 if (lenght > 4)
  112.                 {
  113.                     priceString = errorString;
  114.                     price = double.NaN;
  115.                     return;
  116.                 }
  117.                 errorString = "Err06";
  118.                 int fractionDigits = Math.Max(0, (4 - lenght));
  119.                 errorString = "Err07";
  120.                 double priceValueRounded = Math.Round(priceValue, fractionDigits);
  121.                 errorString = "Err08";
  122.                 priceString = priceValueRounded.ToString(CultureInfo.InvariantCulture);
  123.                 price = priceValueRounded;
  124.             }
  125.             catch
  126.             {
  127.                 priceString = errorString;
  128.                 price = double.NaN;
  129.             }
  130.            
  131.             // code for testing the animation (uncomment this and comment all lines above to use it)
  132. //          Random random = new Random();
  133. //          price = Convert.ToDouble(random.Next(90, 110));
  134. //          priceString = price.ToString(CultureInfo.InvariantCulture);
  135.         }
  136.        
  137.         public void DrawPrice(Graphics g)
  138.         {
  139.             if ((!lastRefresh.IsRunning) || (lastRefresh.ElapsedMilliseconds > RefreshInterval) && (animationPosition == 0))
  140.             {
  141.                 getCurrentPrice();
  142.                 if (AnimationEnabled)
  143.                 {
  144.                     if (!double.IsNaN(price))
  145.                     {
  146.                         if (price > lastPrice)
  147.                             animationPosition = 1;
  148.                         else if (price < lastPrice)
  149.                             animationPosition = -1;
  150.                         else
  151.                             animationPosition = 0;
  152.                     }
  153.                     lastRefresh.Reset();
  154.                     lastRefresh.Start();
  155.                 }
  156.                 else
  157.                 {
  158.                     if (lastPriceString != priceString)
  159.                     {
  160.                         // clear the display
  161.                         g.Clear(Color.White);
  162.                         drawPriceText(g, priceString, AnimationBaseY);
  163.                         lastPriceString = priceString;
  164.                         lastPrice = price;
  165.                     }
  166.                     lastRefresh.Reset();
  167.                     lastRefresh.Start();
  168.                     return;
  169.                 }
  170.                
  171.             }
  172.            
  173.             if (animationPosition == 0)
  174.                 return;
  175.            
  176.             // clear the display
  177.             g.Clear(Color.White);
  178.             drawPriceText(g, lastPriceString, AnimationBaseY + animationPosition);
  179.             if (animationPosition > 0)
  180.             {
  181.                 drawPriceText(g, priceString, AnimationBaseY + animationPosition - 8);
  182.                 animationPosition++;
  183.             }
  184.             else if (animationPosition < 0)
  185.             {
  186.                 drawPriceText(g, priceString, AnimationBaseY + animationPosition + 8);
  187.                 animationPosition--;
  188.             }
  189.             if (Math.Abs(animationPosition) == 9)
  190.             {
  191.                 animationPosition = 0;
  192.                 lastPriceString = priceString;
  193.                 lastPrice = price;
  194.             }
  195.         }
  196.        
  197.         private void drawPriceText(Graphics g, string priceText, int yPos)
  198.         {
  199.             // if this an error message just draw it without using the spacing logics below
  200.             int xPos = -2;
  201.             if (priceText.StartsWith("Err"))
  202.             {
  203.                 g.DrawString(priceText, drawFont, drawBrush, xPos, yPos);
  204.                 return;
  205.             }
  206.            
  207.             // spacing logic starts here
  208.             // 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
  209.            
  210.             int pixelWidth = 0;
  211.             for (int charIndex = 0; charIndex < priceText.Length; charIndex++)
  212.             {
  213.                 if (charIndex > 0)
  214.                     pixelWidth++; // add leading pixel space
  215.                
  216.                 switch (priceText[charIndex])
  217.                 {
  218.                     case '.':
  219.                         pixelWidth += 1;
  220.                         break;
  221.                     case '1':
  222.                         pixelWidth += 2;
  223.                         break;
  224.                     default:
  225.                         pixelWidth += 4;
  226.                         break;
  227.                 }
  228.             }
  229.             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
  230.             bool lastIs4 = (priceText[priceText.Length - 1] == '4');
  231.             if (lastIs4) // if "4" is the last digit we MUST give it the extra pixel so reserve that in the buffer already
  232.                 pixelBuffer--;
  233.            
  234.            
  235.             for (int charIndex = 0; charIndex < priceText.Length; charIndex++)
  236.             {
  237.                 if (priceText[charIndex] == '1')
  238.                     xPos -= 1;
  239.                 if (priceText[charIndex] == '.')
  240.                     xPos -= 1;
  241.                 g.DrawString(priceText.Substring(charIndex, 1), drawFont, drawBrush, xPos, yPos);
  242.                 if (priceText[charIndex] == '.')
  243.                     xPos += 3;
  244.                 else if (priceText[charIndex] == '1')
  245.                     xPos += 4;
  246.                 else if ((priceText[charIndex] == '4') && (pixelBuffer > 0) && (charIndex < (priceText.Length - 1)))
  247.                 {
  248.                     // if this a "4" and we still got spare pixels in the buffer then use it here
  249.                     xPos += 6;
  250.                     pixelBuffer--;
  251.                 }
  252.                 else
  253.                     xPos += 5;
  254.                 if ((charIndex == (priceText.Length - 1)) && (lastIs4)) // if the following last character is a "4" add the extra pixel space we reserved
  255.                     xPos++;
  256.             }
  257.         }
  258.     }
  259.    
  260.    
  261.     #region Currency implementations
  262.     public class USD : LedProgramBase
  263.     {
  264.         Ticker ticker = new Ticker("BTCUSD");
  265.        
  266.         public override int Speed()
  267.         {
  268.             return Ticker.DrawInterval;
  269.         }
  270.        
  271.         public override void Setup(LedUsbDevice device)
  272.         {
  273.         }
  274.        
  275.         protected override void Update(Graphics g)
  276.         {
  277.             ticker.DrawPrice(g);
  278.         }
  279.     }
  280.    
  281.     public class EUR : LedProgramBase
  282.     {
  283.         Ticker ticker = new Ticker("BTCEUR");
  284.        
  285.         public override int Speed()
  286.         {
  287.             return Ticker.DrawInterval;
  288.         }
  289.        
  290.         public override void Setup(LedUsbDevice device)
  291.         {
  292.         }
  293.        
  294.         protected override void Update(Graphics g)
  295.         {
  296.             ticker.DrawPrice(g);
  297.         }
  298.     }
  299.    
  300.     public class CAD : LedProgramBase
  301.     {
  302.         Ticker ticker = new Ticker("BTCCAD");
  303.        
  304.         public override int Speed()
  305.         {
  306.             return Ticker.DrawInterval;
  307.         }
  308.        
  309.         public override void Setup(LedUsbDevice device)
  310.         {
  311.         }
  312.        
  313.         protected override void Update(Graphics g)
  314.         {
  315.             ticker.DrawPrice(g);
  316.         }
  317.     }
  318.    
  319.     public class GBP : LedProgramBase
  320.     {
  321.         Ticker ticker = new Ticker("BTCGBP");
  322.        
  323.         public override int Speed()
  324.         {
  325.             return Ticker.DrawInterval;
  326.         }
  327.        
  328.         public override void Setup(LedUsbDevice device)
  329.         {
  330.         }
  331.        
  332.         protected override void Update(Graphics g)
  333.         {
  334.             ticker.DrawPrice(g);
  335.         }
  336.     }
  337.     #endregion Currency implementations
  338.    
  339. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement