private bool SendFundraiserDataImpl(int threadId, Fundraiser fundraiser)
        {
            bool result = true;
            bool sendData = true;
            String pageId = fundraiser.Id;

            // Check to see if we've sent the data for this fundraiser in the past,
            // if we have then don't bother sending it if it hasn't changed
            if (m_lastSent.ContainsKey(threadId))
            {
                if (m_lastSent[threadId].Equals(fundraiser))
                {
                    sendData = false;
                }
            }

            if (sendData)
            {
                // Lock the fundraiser before sending it - we don't want the storage controller changing it
                // when it's in the middle of being dispatched to output.
                lock (fundraiser.ReadWriteLock)
                {
                    result = m_outputter.SendFundraiser(fundraiser);
                }

                if (result)
                {
                    Fundraiser lastSent = new Fundraiser(pageId);
                    lastSent.CopyDetails(fundraiser);
                    if (m_lastSent.ContainsKey(threadId))
                    {
                        m_lastSent[threadId] = lastSent;
                    }
                    else
                    {
                        m_lastSent.Add(threadId, lastSent);
                    }
                }
            }

            return result;
        }
        /// <summary>
        /// Sends the supplied fundraiser data to the JustGiving rainmeter skin.
        /// </summary>
        /// <param name="fundraiser">The fundraiser to send.</param>
        /// <returns>Whether the operation succeeded.</returns>
        public override bool SendFundraiser(Fundraiser fundraiser)
        {
            bool result = true;
            m_rainmeterDir = ConfigController.GetRainmeterDir();

            // Set all the variables in the rainmeter skin for this fundraiser
            try
            {
                // The rainmeter skin can display a limited number of characters, if the name goes over this then truncate it
                String name = fundraiser.Name;
                if (name.Length > MAX_PAGE_NAME_LENGTH)
                {
                    name = name.Substring(0, MAX_PAGE_NAME_LENGTH - 3) + "...";
                }
                SetRainmeterVariable("fundRaiserName", name);

                if (fundraiser.FundingTarget != null)
                {
                    SetRainmeterVariable("fundingTarget", fundraiser.FundingTarget.ToString());
                }
                else
                {
                    SetRainmeterVariable("fundingTarget", String.Empty);
                }
                SetRainmeterVariable("currentFunding", Decimal.Parse(fundraiser.CurrentFunding).ToString("#.##"));
                SetRainmeterVariable("currencySymbol", fundraiser.CurrencySymbol);
                SetRainmeterVariable("endDate", fundraiser.EndDate.ToString("dd/MM/yyyy"));

                for (int i = 0; i < fundraiser.Donations.Count; i++)
                {
                    Donation donation = fundraiser.Donations[i];

                    String dateVarName = String.Format("donation{0}Date", i + 1);
                    String nameVarName = String.Format("donation{0}Name", i + 1);
                    String valueVarName = String.Format("donation{0}Value", i + 1);

                    if (donation.Date != null)
                    {
                        SetRainmeterVariable(dateVarName, ((DateTime)donation.Date).ToString("dd/MM/yyyy"));
                    }
                    else
                    {
                        SetRainmeterVariable(dateVarName, String.Empty);
                    }

                    // The rainmeter skin can display a limited number of characters, if the donator's name goes over this then truncate it
                    String donatorName = donation.Name;
                    if (donatorName.Length > MAX_DONATOR_NAME_LENGTH)
                    {
                        name = name.Substring(0, MAX_DONATOR_NAME_LENGTH - 3) + "...";
                    }
                    SetRainmeterVariable(nameVarName, donatorName);

                    if (donation.Value != null)
                    {
                        // The rainmeter skin requires us to add the currency symbol to the start of the donation amount.
                        Decimal value = (Decimal)donation.Value;
                        String valueString = String.Format("{0}{1}", fundraiser.CurrencySymbol, value.ToString("F"));
                        SetRainmeterVariable(valueVarName, valueString);
                    }
                    else
                    {
                        SetRainmeterVariable(valueVarName, String.Empty);
                    }
                }
            }
            catch (Exception e)
            {
                // There's been an error setting one of the variables.
                result = false;
            }

            return result;
        }
 public static bool SendFundraiserData(int threadId, Fundraiser fundraiser)
 {
     return Instance.SendFundraiserDataImpl(threadId, fundraiser);
 }
 private void AddFundraiserImpl(Fundraiser newFundraiser)
 {
     m_fundraisers.Add(newFundraiser.Id, newFundraiser);
 }
 public static void AddFundraiser(Fundraiser newFundraiser)
 {
     Instance.AddFundraiserImpl(newFundraiser);
 }
 public void CopyDetails(Fundraiser newFundraiser)
 {
     // Check that these are actually the same fundraising page
     if (Id == newFundraiser.Id)
     {
         Name = newFundraiser.Name;
         FundingTarget = newFundraiser.FundingTarget;
         CurrentFunding = newFundraiser.CurrentFunding;
         CurrencySymbol = newFundraiser.CurrencySymbol;
         EndDate = newFundraiser.EndDate;
         Donations = newFundraiser.Donations;
     }
     else
     {
         throw new InvalidOperationException("Invalid fundraiser ID - ID of the new page must match the existing ID.");
     }
 }
        // Entry point for threads which periodically poll for a fundraiser's details.
        public static void EntryPoint(object threadId)
        {
            int threadIdInt = (int)threadId;

            // Create the API client
            JustGivingClient client = new JustGivingClient("9cce4750");

            // Enter the loop which polls the API periodically
            while (true)
            {
                // Get the page ID from the config controller based on this thread's thread ID
                String pageId = ConfigController.GetPageIds()[threadIdInt];
                int pollingPeriod = ConfigController.GetApiPollingPeriod();

                // Get the page
                FundraisingPage page = client.Page.Retrieve(pageId);

                if (page != null)
                {
                    // Get the information we need and put it in to our model
                    string id = pageId;
                    string name = page.PageTitle;
                    decimal? fundingTarget = page.TargetAmount;
                    string currentFunding = page.TotalRaised;
                    string currencySymbol = page.CurrencySymbol;
                    DateTime endDate = page.PageExpiryDate;
                    List<Model.Donation> recentDonations = new List<Model.Donation>();

                    // Get the donations with a separate API call
                    FundraisingPageDonations pageDonations = client.Page.RetrieveDonationsForPage(pageId);
                    List<FundraisingPageDonation> donations = pageDonations.Donations;
                    for (int i = 0; i < donations.Count && i < MAX_RECENT_DONATIONS; i++)
                    {
                        FundraisingPageDonation donation = donations[i];

                        DateTime? date = donation.DonationDate;
                        string donator = donation.DonorDisplayName;
                        decimal? value = donation.Amount;

                        Model.Donation newDonation = new Model.Donation(date, donator, value);
                        recentDonations.Add(newDonation);
                    }

                    Fundraiser fundraiser = new Fundraiser(id,
                        name,
                        fundingTarget,
                        currentFunding,
                        currencySymbol,
                        endDate,
                        recentDonations);

                    // Check to see whether the storage controller currently has this fundraiser stored
                    Fundraiser existingFundraiser = DataStorageController.GetFundraiser(pageId);
                    if (existingFundraiser == null)
                    {
                        // It doesn't exist yet, so just add it
                        DataStorageController.AddFundraiser(fundraiser);
                    }
                    else
                    {
                        // There's an existing item, lock it and then copy over the new details
                        lock (existingFundraiser.ReadWriteLock)
                        {
                            existingFundraiser.CopyDetails(fundraiser);
                        }
                    }
                }

                Thread.Sleep(pollingPeriod);
            }
        }
 /// <summary>
 /// Sends fundraiser data to an external application
 /// </summary>
 /// <param name="fundraiser">The fundraiser to send</param>
 /// <returns>Whether the operation succeeded.</returns>
 public abstract bool SendFundraiser(Fundraiser fundraiser);