コード例 #1
0
ファイル: List.aspx.cs プロジェクト: anthrax3/Swarmops
    private static void RebuildMembershipCacheForOrg(int handledOrgId)
    {
        Organizations           orgs = Organization.FromIdentity(handledOrgId).GetTree();
        Memberships             ms   = Memberships.ForOrganizations(orgs, false);
        OrgMembershipCacheEntry msc  = null;

        foreach (Activizr.Logic.Pirates.Membership m in ms)
        {
            if (!membershipCache.ContainsKey(m.OrganizationId))
            {
                msc             = new OrgMembershipCacheEntry();
                msc.memberships = new Dictionary <int, Activizr.Logic.Pirates.Membership>();
                membershipCache[m.OrganizationId] = msc;
            }
            else
            {
                msc = membershipCache[m.OrganizationId];
            }

            msc.membershipCacheTime     = DateTime.Now;
            msc.memberships[m.PersonId] = m;
            msc.orgId = m.OrganizationId;
        }
    }
コード例 #2
0
        static public void Run()
        {
            MeetingElections polls = MeetingElections.GetAll();

            foreach (MeetingElection poll in polls)
            {
                Console.Write("Looking at poll #" + poll.Identity.ToString() + "...");

                if (DateTime.Now > poll.VotingCloses)
                {
                    Console.Write(" after closedatetime " + poll.VotingCloses.ToString("yyyy-MM-dd HH:mm") + "...");

                    // Poll should be CLOSED, definitely CLOSED.

                    if (poll.VotingOpen)
                    {
                        Console.WriteLine(" CLOSING.");

                        poll.VotingOpen = false; // Closes poll
                        poll.Creator.SendNotice("Poll Closed: " + poll.Name, string.Empty, poll.OrganizationId);
                        Person.FromIdentity(1).SendNotice("Poll Closed: " + poll.Name, string.Empty, poll.OrganizationId);

                        ReportPollResults(poll, false);
                    }
                    else
                    {
                        Console.WriteLine(" no action.");
                    }
                }
                else if (DateTime.Now > poll.VotingOpens)
                {
                    try
                    {
                        // Poll should be OPEN.

                        Console.Write("after opendatetime " + poll.VotingOpens.ToString("yyyy-MM-dd HH:mm") + "...");

                        if (!poll.VotingOpen)
                        {
                            Console.WriteLine("OPENING for " + poll.Organization.Name + ":");

                            // Populate voters, then open for voting

                            Organizations orgTree = poll.Organization.GetTree();

                            Memberships memberships = Memberships.ForOrganizations(orgTree);

                            Dictionary <int, bool> dupeCheck = new Dictionary <int, bool>();

                            int count = 0;

                            foreach (Membership membership in memberships)
                            {
                                Console.Write("\r - voters: {0:D6}/{1:D6} (person #{2:D6})...", ++count, memberships.Count, membership.PersonId);

                                if (!membership.Active)
                                {
                                    continue; // paranoid programming
                                }

                                if (!membership.Organization.IsOrInherits(poll.Organization))
                                {
                                    continue; // more paranoid programming
                                }

                                if (!dupeCheck.ContainsKey(membership.PersonId))
                                {
                                    if (membership.Person.GeographyId == 0)
                                    {
                                        // It's a trap!

                                        Console.Write(" GEOGRAPHY ZERO, ignoring\r\n");
                                    }
                                    else
                                    {
                                        Geography geo = membership.Person.Geography;

                                        if (geo.Inherits(poll.GeographyId) || geo.Identity == poll.GeographyId)
                                        {
                                            poll.AddVoter(membership.Person);
                                            dupeCheck[membership.PersonId] = true;
                                        }
                                    }
                                }
                            }

                            Console.WriteLine(" done.");
                            Console.Write(" - opening poll...");

                            poll.VotingOpen = true;

                            Console.WriteLine(" done.");
                            Console.Write("Sending notices... ");

                            string body = "Electoral roll for poll \"" + poll.Name + "\" primed. " +
                                          dupeCheck.Count.ToString() + " people can vote. The vote is now OPEN.";

                            string subject = "Poll Open: " + poll.Name;

                            poll.Creator.SendNotice(subject, body, poll.OrganizationId);
                            Person.FromIdentity(1).SendNotice(subject, body, poll.OrganizationId);

                            Console.WriteLine(" done.");
                        }
                        else
                        {
                            Console.WriteLine(" already open, no action.");

                            // Report intermediate results to owner

                            ReportPollResults(poll, true);
                        }
                    }
                    catch (Exception exception)
                    {
                        Console.WriteLine(exception.ToString());

                        throw exception;
                    }
                }
            }
        }
コード例 #3
0
    SeriesCollection GetAgeGenderData(OrganizationMetadata metadata)
    {
        int  orgId       = metadata.OrganizationId;
        bool recurseTree = metadata.Recursive;

        Series seriesMale   = new Series();
        Series seriesFemale = new Series();

        seriesMale.Name   = "Male";
        seriesFemale.Name = "Female";

        Memberships memberships = null;

        if (recurseTree)
        {
            memberships = Memberships.ForOrganizations(Organization.FromIdentity(orgId).GetTree());
        }
        else
        {
            memberships = Memberships.ForOrganization(Organization.FromIdentity(orgId));
        }

        BasicPerson[] allPeople = PirateDb.GetDatabase().GetAllPeople();

        Dictionary <int, int>          geoLookup       = new Dictionary <int, int>();
        Dictionary <int, PersonGender> genderLookup    = new Dictionary <int, PersonGender>();
        Dictionary <int, int>          birthYearLookup = new Dictionary <int, int>();
        Dictionary <int, bool>         personLookup    = new Dictionary <int, bool>();

        foreach (BasicPerson person in allPeople)
        {
            geoLookup[person.Identity]       = person.GeographyId;
            genderLookup[person.Identity]    = person.IsMale ? PersonGender.Male : PersonGender.Female;
            birthYearLookup[person.Identity] = person.Birthdate.Year;
        }

        int[] male   = new int[200];
        int[] female = new int[200];

        foreach (Membership membership in memberships)
        {
            int          birthYear = 0;
            PersonGender gender    = PersonGender.Unknown;

            if (personLookup.ContainsKey(membership.PersonId))
            {
                continue; // If a person was already counted, do not count again
            }

            if (genderLookup.ContainsKey(membership.PersonId) &&
                (membership.OrganizationId == orgId ||
                 (recurseTree && membership.Organization.Inherits(orgId))))
            {
                birthYear = birthYearLookup[membership.PersonId];
                gender    = genderLookup[membership.PersonId];

                int index = birthYear - 1900;

                if (index < 30 || index >= 100)
                {
                    index = 90; // Put invalid years on 1990, where it won't show up in the noise
                }

                if (gender == PersonGender.Male)
                {
                    male[index]++;
                }
                else
                {
                    female[index]++;
                }

                personLookup[membership.PersonId] = true;
            }
        }

        Element newElement = new Element();

        for (int yearIndex = 30; yearIndex < 100; yearIndex++)
        {
            newElement        = new Element();
            newElement.Name   = (1900 + yearIndex).ToString();
            newElement.YValue = male[yearIndex];
            seriesMale.Elements.Add(newElement);

            newElement        = new Element();
            newElement.Name   = (1900 + yearIndex).ToString();
            newElement.YValue = female[yearIndex];
            seriesFemale.Elements.Add(newElement);
        }

        seriesMale.DefaultElement.Color   = Color.Blue;
        seriesFemale.DefaultElement.Color = Color.Red;

        SeriesCollection collection = new SeriesCollection();

        collection.Add(seriesFemale);
        collection.Add(seriesMale);

        return(collection);
    }
コード例 #4
0
        public static GeographyStatistics GeneratePresent(int[] memberCountForOrganizations)
        {
            Dictionary <int, int> voterCounts = SwarmDb.GetDatabaseForReading().GetGeographyVoterCounts();
            var result = new GeographyStatistics();

            // Step 1 - tally the leaf nodes

            foreach (int geographyId in voterCounts.Keys)
            {
                var dataPoint = new GeographyDataPoint
                {
                    GeographyName = Geography.FromIdentity(geographyId).Name,
                    GeographyId   = geographyId,
                    VoterCount    = voterCounts[geographyId]
                };

                result[geographyId] = dataPoint;
            }


            // Step 2 - add the member counts to the individual requested geo nodes

            foreach (int orgId in memberCountForOrganizations)
            {
                People members =
                    People.FromMemberships(
                        Memberships.ForOrganizations(Organization.FromIdentity(orgId).GetTree()));

                foreach (Person person in members)
                {
                    Geography geography = person.Geography;

                    // If we don't have this key, it's because it's too far down. Move up the tree until we're at least
                    // at municipal level.

                    while (geography.Identity != 1 && !result.ContainsKey(geography.Identity))
                    {
                        geography = geography.Parent;
                    }

                    // Add the data, unless we hit the roof in the last op.

                    if (geography.Identity != 1)
                    {
                        int birthYearBracket = (person.Birthdate.Year - 1900) / 5;

                        if (birthYearBracket >= 0 && birthYearBracket < 30)
                        {
                            result[geography.Identity].OrganizationData[orgId - 1].BirthYearBracketMemberCounts[
                                birthYearBracket]++;
                        }

                        if (person.IsFemale)
                        {
                            result[geography.Identity].OrganizationData[orgId - 1].FemaleMemberCount++;
                        }
                        else if (person.IsMale)
                        {
                            result[geography.Identity].OrganizationData[orgId - 1].MaleMemberCount++;
                        }
                    }
                }
            }

            // TODO: Activist count as a new step


            // Step 3 - add up the totals for every intermediate node (expensive!)

            Geographies allGeographies = Geography.Root.GetTree();

            foreach (Geography geography in allGeographies)
            {
                Geographies localTree   = geography.GetTree();
                int         voterCount  = 0;
                var         tempOrgData = new GeographyOrganizationDataPoint[2]; // HACK
                tempOrgData[0] = new GeographyOrganizationDataPoint();
                tempOrgData[1] = new GeographyOrganizationDataPoint();

                foreach (Geography localNode in localTree)
                {
                    // Increment our temp values for every geo node below the one we're currently processing.

                    if (!result.ContainsKey(localNode.Identity))
                    {
                        continue;
                    }

                    voterCount += result[localNode.Identity].VoterCount;

                    for (int orgIndex = 0; orgIndex < 2; orgIndex++)
                    {
                        for (int ageBracketIndex = 0; ageBracketIndex < 30; ageBracketIndex++)
                        {
                            tempOrgData[orgIndex].BirthYearBracketMemberCounts[ageBracketIndex] +=
                                result[localNode.Identity].OrganizationData[orgIndex].BirthYearBracketMemberCounts[
                                    ageBracketIndex];
                        }

                        tempOrgData[orgIndex].ActivistCount +=
                            result[localNode.Identity].OrganizationData[orgIndex].ActivistCount;
                        tempOrgData[orgIndex].FemaleMemberCount +=
                            result[localNode.Identity].OrganizationData[orgIndex].FemaleMemberCount;
                        tempOrgData[orgIndex].MaleMemberCount +=
                            result[localNode.Identity].OrganizationData[orgIndex].MaleMemberCount;
                    }
                }

                if (!result.ContainsKey(geography.Identity))
                {
                    result[geography.Identity] = new GeographyDataPoint
                    {
                        GeographyId   = geography.Identity,
                        GeographyName = geography.Name
                    };
                }

                // Save our temp values to the processed node.

                result[geography.Identity].VoterCount = voterCount;

                for (int orgIndex = 0; orgIndex < 2; orgIndex++)
                {
                    for (int ageBracketIndex = 0; ageBracketIndex < 30; ageBracketIndex++)
                    {
                        result[geography.Identity].OrganizationData[orgIndex].BirthYearBracketMemberCounts[
                            ageBracketIndex] =
                            tempOrgData[orgIndex].BirthYearBracketMemberCounts[ageBracketIndex];
                    }

                    result[geography.Identity].OrganizationData[orgIndex].ActivistCount =
                        tempOrgData[orgIndex].ActivistCount;
                    result[geography.Identity].OrganizationData[orgIndex].FemaleMemberCount =
                        tempOrgData[orgIndex].FemaleMemberCount;
                    result[geography.Identity].OrganizationData[orgIndex].MaleMemberCount =
                        tempOrgData[orgIndex].MaleMemberCount;
                }
            }


            // Step 4 - collect

            return(result);
        }
コード例 #5
0
ファイル: Export.aspx.cs プロジェクト: osoftware/Swarmops
    protected void Page_Load(object sender, EventArgs e)
    {
        string   fileName     = DateTime.Now.ToString("yyyyMMdd_HHmm") + ".txt";
        DateTime specificDate = DateTime.MinValue;
        DateTime yearLimit    = DateTime.Today.AddYears(-1);

        if (Request["Date"] != null)
        {
            DateTime.TryParse(Request["Date"].ToString(), out specificDate);
            if (specificDate != DateTime.MinValue)
            {
                fileName     = "[" + specificDate.ToString("yyyyMMdd_HHmm") + "]" + fileName;
                specificDate = specificDate.AddDays(1);
                yearLimit    = specificDate.AddYears(-1);
                specificDate = specificDate.AddSeconds(-1);
            }
        }

        if (Request.Browser.Browser == "IE")
        {
            fileName = Server.UrlPathEncode(fileName);

            if (fileName != null)
            {
                fileName = fileName.Replace(@"+", @"%20");
            }
        }
        int          org          = Organization.UPSEid;
        Organization organization = Organization.FromIdentity(org);

        fileName = organization.NameShort + fileName;


        Response.ContentType     = "text/plain";
        Response.ContentEncoding = Encoding.GetEncoding(1252);

        //Response.ContentType = "application/octet-stream";

        Response.AddHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\";");


        if (_authority.HasRoleAtOrganization(organization, new RoleType[] { RoleType.OrganizationChairman, RoleType.OrganizationSecretary }, Authorization.Flag.AnyGeographyExactOrganization) ||
            _authority.HasRoleType(RoleType.SystemAdmin))
        {
            People ThePeople = People.GetAll().RemoveUnlisted();

            Memberships MembershipsList = null;
            if (Request["Date"] != null)
            {
                MembershipsList = Memberships.FromArray(PirateDb.GetDatabase().GetMemberships());  // gets ALL memberships
            }
            else
            {
                MembershipsList = Memberships.ForOrganizations(Organization.FromIdentity(org).GetTree());
            }

            Dictionary <int, string> GeoDistriktForGeo = new Dictionary <int, string>();
            Dictionary <int, string> OrgDistriktForOrg = new Dictionary <int, string>();


            Dictionary <int, Memberships> ActiveMemberships = new Dictionary <int, Memberships>();
            foreach (Membership ms in MembershipsList)
            {
                if (ms.OrganizationId == org || ms.Organization.Inherits(org))
                {
                    if (specificDate != DateTime.MinValue)
                    {
                        if ((ms.Active || ms.DateTerminated > specificDate) && // Rick replaced "DateTerminated.HasValue" with "Active=1"
                            ms.Expires > specificDate &&
                            ms.MemberSince <= specificDate)
                        {
                            if (!ActiveMemberships.ContainsKey(ms.PersonId))
                            {
                                ActiveMemberships.Add(ms.PersonId, new Memberships());
                            }
                            ActiveMemberships[ms.PersonId].Add(ms);
                        }
                    }
                    else if (ms.Active)
                    {
                        if (!ActiveMemberships.ContainsKey(ms.PersonId))
                        {
                            ActiveMemberships.Add(ms.PersonId, new Memberships());
                        }
                        ActiveMemberships[ms.PersonId].Add(ms);
                    }
                }
            }

            List <int> idlist = new List <int>();
            Dictionary <int, List <BasicPWEvent> > personLogs = new Dictionary <int, List <BasicPWEvent> >();
            foreach (int pId in ActiveMemberships.Keys)
            {
                idlist.Add(pId);
                if (idlist.Count > 500)
                {
                    FetchBatchOfLogs(ref specificDate, ref yearLimit, idlist, personLogs);

                    idlist = new List <int>();
                }
            }

            if (idlist.Count > 0)
            {
                FetchBatchOfLogs(ref specificDate, ref yearLimit, idlist, personLogs);
            }


            StringBuilder sb = new StringBuilder();

            sb.Append("Identity");
            sb.Append("\tName");
            sb.Append("\tEmail");
            sb.Append("\tStreet");
            sb.Append("\tPostalCode");
            sb.Append("\tCity");
            sb.Append("\tCountry.Name");
            sb.Append("\tPhone");
            sb.Append("\tBirthdate");
            sb.Append("\tGender");
            sb.Append("\tGeography.Name");
            sb.Append("\tGeography.District");
            sb.Append("\tOrganization.Name");
            sb.Append("\tOrganization.District");
            sb.Append("\tMembership.start");
            sb.Append("\tMembership.until");
            sb.Append("\tRenewed");
            sb.Append("\tType");
            sb.Append("\tby");
            sb.Append("\tfrom");
            sb.Append("\r\n");


            foreach (Person p in ThePeople)
            {
                if (ActiveMemberships.ContainsKey(p.PersonId))
                {
                    Memberships pMemberships = ActiveMemberships[p.PersonId];
                    foreach (Membership m in pMemberships)
                    {
                        if (!GeoDistriktForGeo.ContainsKey(p.GeographyId))
                        {
                            Geography currentGeoDistr = null;
                            GeoDistriktForGeo[p.GeographyId] = "N/A";
                            if (p.GeographyId != 0)
                            {
                                try
                                {
                                    Geography previous = p.Geography;

                                    if (p.Geography.ParentGeographyId != 0)
                                    {
                                        currentGeoDistr = p.Geography.Parent;
                                    }

                                    while (currentGeoDistr != null &&
                                           currentGeoDistr.Identity != 0 &&
                                           currentGeoDistr.Identity != Geography.SwedenId &&
                                           currentGeoDistr.Identity != Geography.RootIdentity)
                                    {
                                        previous = currentGeoDistr;
                                        if (currentGeoDistr.ParentGeographyId == 0)
                                        {
                                            currentGeoDistr = null;
                                        }
                                        else
                                        {
                                            currentGeoDistr = currentGeoDistr.Parent;
                                        }
                                    }
                                    if (previous != null)
                                    {
                                        GeoDistriktForGeo[p.GeographyId] = previous.Name;
                                    }
                                }
                                catch (Exception ex)
                                {
                                    GeoDistriktForGeo[p.GeographyId] = "n/a";
                                }
                            }
                        }

                        if (!OrgDistriktForOrg.ContainsKey(m.OrganizationId))
                        {
                            Organization currentOrgDistr = null;
                            OrgDistriktForOrg[m.OrganizationId] = "N/A";

                            Organization previous = m.Organization;
                            currentOrgDistr = m.Organization.Parent;;

                            while (currentOrgDistr != null &&
                                   currentOrgDistr.Identity != 0 &&
                                   currentOrgDistr.Identity != org &&
                                   currentOrgDistr.Identity != Organization.RootIdentity)
                            {
                                previous = currentOrgDistr;
                                if (currentOrgDistr.ParentOrganizationId == 0)
                                {
                                    currentOrgDistr = null;
                                }
                                else
                                {
                                    currentOrgDistr = currentOrgDistr.Parent;
                                }
                            }
                            if (previous != null)
                            {
                                OrgDistriktForOrg[m.OrganizationId] = previous.NameShort;
                            }
                        }

                        sb.Append(p.Identity);
                        sb.Append("\t" + p.Name.Replace("\t", ""));
                        sb.Append("\t" + p.Email.Replace("\t", ""));
                        sb.Append("\t" + p.Street.Replace("\t", ""));
                        sb.Append("\t" + p.PostalCode.Replace("\t", ""));
                        sb.Append("\t" + p.CityName.Replace("\t", ""));
                        sb.Append("\t" + p.Country.Name.Replace("\t", ""));
                        sb.Append("\t" + p.Phone.Replace("\t", ""));
                        sb.Append("\t" + p.Birthdate);
                        sb.Append("\t" + p.Gender);
                        sb.Append("\t" + p.Geography.Name);
                        sb.Append("\t" + GeoDistriktForGeo[p.GeographyId]);
                        sb.Append("\t" + m.Organization.Name);
                        sb.Append("\t" + OrgDistriktForOrg[m.OrganizationId]);
                        sb.Append("\t" + m.MemberSince);
                        if (!m.Active)
                        {
                            sb.Append("\t" + m.DateTerminated);
                        }
                        else
                        {
                            sb.Append("\t" + m.Expires);
                        }

                        if (personLogs.ContainsKey(p.Identity))
                        {
                            bool found = false;
                            foreach (BasicPWEvent log in personLogs[p.Identity])
                            {
                                if (log.OrganizationId == m.OrganizationId)
                                {
                                    sb.Append("\t" + log.DateTime);
                                    sb.Append("\t" + log.EventType);
                                    sb.Append("\t" + log.ActingPersonId);
                                    sb.Append("\t" + log.ParameterText);
                                    found = true;
                                    break;
                                }
                            }
                            if (!found)
                            {
                                sb.Append("\t\t\t\t");
                            }
                        }
                        else
                        {
                            sb.Append("\t\t\t\t");
                        }
                        sb.Append("\r\n");
                    }
                }
            }

            Response.Write(sb.ToString());
        }
    }
コード例 #6
0
    SeriesCollection GetAgeGenderData()
    {
        string orgIdString       = Request.QueryString["OrgId"];
        string recurseTreeString = Request.QueryString["RecurseTree"];

        int  orgId       = Organization.PPSEid;
        bool recurseTree = false;

        if (orgIdString != null)
        {
            orgId = Int32.Parse(orgIdString);
        }

        if (recurseTreeString == "1")
        {
            recurseTree = true;
        }

        Chart.ChartArea.YAxis.Label.Text = "Medlems\xE5ldrar och k\xF6n - " + Organization.FromIdentity(orgId).Name;

        Series seriesMale   = new Series();
        Series seriesFemale = new Series();

        seriesMale.Name   = "M\xE4n";
        seriesFemale.Name = "Kvinnor";

        Memberships memberships = null;

        if (recurseTree)
        {
            memberships = Memberships.ForOrganizations(Organization.FromIdentity(orgId).GetTree());
        }
        else
        {
            memberships = Memberships.ForOrganization(Organization.FromIdentity(orgId));
        }

        BasicPerson[] allPeople = PirateDb.GetDatabase().GetAllPeople();

        Dictionary <int, int>          geoLookup       = new Dictionary <int, int>();
        Dictionary <int, PersonGender> genderLookup    = new Dictionary <int, PersonGender>();
        Dictionary <int, int>          birthYearLookup = new Dictionary <int, int>();
        Dictionary <int, int>          personLookup    = new Dictionary <int, int>();

        foreach (BasicPerson person in allPeople)
        {
            geoLookup[person.Identity]       = person.GeographyId;
            genderLookup[person.Identity]    = person.IsMale ? PersonGender.Male : PersonGender.Female;
            birthYearLookup[person.Identity] = person.Birthdate.Year;
        }

        int[] male   = new int[200];
        int[] female = new int[200];

        foreach (Membership membership in memberships)
        {
            int          birthYear = 0;
            PersonGender gender    = PersonGender.Unknown;

            if (genderLookup.ContainsKey(membership.PersonId) &&
                !personLookup.ContainsKey(membership.PersonId) &&
                (membership.OrganizationId == orgId ||
                 (recurseTree && membership.Organization.Inherits(orgId))))
            {
                personLookup[membership.PersonId] = 1;

                birthYear = birthYearLookup[membership.PersonId];
                gender    = genderLookup[membership.PersonId];

                if (birthYear > 1900 && birthYear < (1900 + 200))
                {
                    if (gender == PersonGender.Male)
                    {
                        male[birthYear - 1900]++;
                    }
                    else
                    {
                        female[birthYear - 1900]++;
                    }
                }
            }
        }

        Element newElement = new Element();

        for (int yearIndex = 30; yearIndex <= 100; yearIndex++)
        {
            newElement        = new Element();
            newElement.Name   = (1900 + yearIndex).ToString();
            newElement.YValue = male[yearIndex];
            seriesMale.Elements.Add(newElement);

            newElement        = new Element();
            newElement.Name   = (1900 + yearIndex).ToString();
            newElement.YValue = female[yearIndex];
            seriesFemale.Elements.Add(newElement);
        }


        seriesMale.DefaultElement.Color   = Color.Blue;
        seriesFemale.DefaultElement.Color = Color.Red;

        SeriesCollection collection = new SeriesCollection();

        collection.Add(seriesFemale);
        collection.Add(seriesMale);

        return(collection);
    }
コード例 #7
0
        public static void RemindChangeOrg()
        {
            HeartBeater.Instance.Beat();

            // Get expiring
            DateTime                       starttime                  = DateTime.Now;
            Organizations                  orgs                       = Organization.FromIdentity(Organization.UPSEid).GetTree();
            Dictionary <int, Person>       personLookup               = new Dictionary <int, Person>();
            Dictionary <int, Memberships>  personMembershipsLookup    = new Dictionary <int, Memberships>();
            Dictionary <int, Organization> orgLookup                  = new Dictionary <int, Organization>();
            Dictionary <int, Organization> mostLocalOrganizationCache = new Dictionary <int, Organization>();
            List <ChangeOrgReport>         report                     = new List <ChangeOrgReport>();

            foreach (Organization org in orgs)
            {
                orgLookup[org.OrganizationId] = org;
            }

            Memberships allMemberships = Memberships.ForOrganizations(orgs);

            foreach (Membership ms in allMemberships)
            {
                //Handle defunct Memberships.ForOrganizations
                if (orgLookup.ContainsKey(ms.OrganizationId))
                {
                    if (!personLookup.ContainsKey(ms.PersonId))
                    {
                        personLookup[ms.PersonId]            = null;
                        personMembershipsLookup[ms.PersonId] = new Memberships();
                    }
                    personMembershipsLookup[ms.PersonId].Add(ms);
                }
            }
            allMemberships = null;

            People peeps = People.FromIdentities((new List <int>(personLookup.Keys)).ToArray());

            foreach (Person p in peeps)
            {
                personLookup[p.PersonId] = p;
            }


            if (Debugger.IsAttached)
            {
                Console.WriteLine("Found " + personLookup.Count + " people");
            }

            int processedCounter = 0;
            int sentCounter      = 0;
            int failCounter      = 0;

            DateTime lastDisplay = DateTime.Now;

            foreach (Person person in personLookup.Values)
            {
                ++processedCounter;
                if ((processedCounter % 50) == 0)
                {
                    HeartBeater.Instance.Beat();
                    if (Debugger.IsAttached)
                    {
                        Console.WriteLine("Processed " + processedCounter + " t=" + DateTime.Now.Subtract(lastDisplay).TotalSeconds);
                    }
                    lastDisplay = DateTime.Now;
                }

                int geoid = person.GeographyId;

                //check for error, geography broken.
                if (person.GeographyId == 0)
                {
                    geoid = person.Geography.GeographyId; //Will force resolve Geography
                    if (geoid != 0)
                    {
                        person.Geography = person.Geography;
                    }
                    ;                                          //repair person.
                }

                if (geoid == 0)
                {
                    continue; //give up on that...
                }
                Organization expectedLowOrg = null;

                if (mostLocalOrganizationCache.ContainsKey(geoid))
                {
                    expectedLowOrg = mostLocalOrganizationCache[geoid];
                }
                else
                {
                    expectedLowOrg = Organizations.GetMostLocalOrganization(geoid, Organization.UPSEid);
                    mostLocalOrganizationCache[geoid] = expectedLowOrg;
                }

                bool found = false;
                Dictionary <int, Membership> personMS = new Dictionary <int, Membership>();

                foreach (Membership ms in personMembershipsLookup[person.PersonId])
                {
                    if (orgLookup.ContainsKey(ms.OrganizationId))
                    {   //Its an UP org
                        personMS[ms.OrganizationId] = ms;
                    }
                    if (ms.OrganizationId == expectedLowOrg.Identity)
                    {
                        found = true;
                        break;
                    }
                }

                if (found == false)
                {
                    //OK we didnt find the recommended org. Find out why.

                    // loop thru the persons up orgs to find an inactive
                    List <Organization> foundInactiveOrg = new List <Organization>();
                    List <Organization> foundActiveOrg   = new List <Organization>();
                    Membership          membership       = null;
                    try
                    {
                        Organization org = null;

                        foreach (Membership ms in personMS.Values)
                        {
                            org = orgLookup[ms.OrganizationId];
                            if (org.AcceptsMembers == false)
                            {
                                foundInactiveOrg.Add(org);
                            }
                            else if (org.AutoAssignNewMembers == true)
                            {
                                foundActiveOrg.Add(org);
                            }
                        }

                        if (foundInactiveOrg.Count > 0)
                        {
                            //inactive
                            membership = personMS[foundInactiveOrg[0].Identity];
                        }
                        else if (foundActiveOrg.Count > 0)
                        {
                            //change
                            membership = personMS[foundActiveOrg[0].Identity];
                        }
                        else
                        {
                            //already a member but not of an autoassign org
                            if (Debugger.IsAttached)
                            {
                                Console.WriteLine("Debug:nochange " + person.Name + ";" + person.Geography.Name + ";" + (org != null ? org.Name : "UnknownOrg") + ";" + expectedLowOrg.Name);
                            }
                            continue;
                        }
                        DateTime lastReminder = PWLog.CheckLatest(PWLogItem.Person, membership.PersonId, PWLogAction.MembershipRenewReminder);

                        if (DateTime.Now.Subtract(lastReminder).TotalDays > 25)
                        {
                            if (Debugger.IsAttached)
                            {
                                Console.Write("Debug:" + person.Name + ";" + person.Geography.Name + ";" + membership.Organization.Name + ";" + expectedLowOrg.Name);
                                foreach (var o in foundActiveOrg)
                                {
                                    Console.Write(";" + o.Name);
                                }
                                Console.WriteLine("");
                            }

                            SendChangeOrgMail(person, membership, expectedLowOrg);
                            report.Add(new ChangeOrgReport {
                                FromOrg = membership.Organization, ToOrg = expectedLowOrg
                            });
                            ++sentCounter;
                            PWLog.Write(PWLogItem.Person, membership.PersonId,
                                        PWLogAction.MembershipRenewReminder,
                                        "Mail was sent to " + membership.Person.Mail +
                                        " for recommendation of organisation change in " + membership.Organization.Name + ".",
                                        membership.Organization.Identity.ToString() + "/" + expectedLowOrg.Identity.ToString());
                        }
                    }
                    catch (Exception x)
                    {
                        ++failCounter;
                        string logText = "FAILED sending mail to " + membership.Person.Mail +
                                         " for recommendation of organisation change in " + membership.Organization.Name + ".";
                        PWLog.Write(PWLogItem.Person, membership.PersonId,
                                    PWLogAction.MembershipRenewReminder,
                                    logText, string.Empty);
                        ExceptionMail.Send(new Exception(logText, x));
                    }
                }
            }

            Dictionary <Organization, Dictionary <Organization, int> > fromdict = new Dictionary <Organization, Dictionary <Organization, int> >();
            StringBuilder fromOrgReport = new StringBuilder();

            report.ForEach(delegate(ChangeOrgReport r)
            {
                if (!fromdict.ContainsKey(r.FromOrg))
                {
                    fromdict[r.FromOrg] = new Dictionary <Organization, int>();
                }
                if (!fromdict[r.FromOrg].ContainsKey(r.ToOrg))
                {
                    fromdict[r.FromOrg][r.ToOrg] = 0;
                }
                fromdict[r.FromOrg][r.ToOrg]++;
            });
            foreach (var fd in fromdict.Keys)
            {
                StringBuilder tmp = new StringBuilder();
                int           cnt = 0;
                foreach (var td in fromdict[fd].Keys)
                {
                    tmp.Append(", " + td.Name);
                    cnt += fromdict[fd][td];
                }
                fromOrgReport.Append("\r\nFrån " + fd.Name + " (" + cnt + " st) till " + tmp.ToString().Substring(2));
            }

            Dictionary <Organization, Dictionary <Organization, int> > todict = new Dictionary <Organization, Dictionary <Organization, int> >();
            StringBuilder toOrgReport = new StringBuilder();

            report.ForEach(delegate(ChangeOrgReport r)
            {
                if (!todict.ContainsKey(r.ToOrg))
                {
                    todict[r.ToOrg] = new Dictionary <Organization, int>();
                }
                if (!todict[r.ToOrg].ContainsKey(r.FromOrg))
                {
                    todict[r.ToOrg][r.FromOrg] = 0;
                }
                todict[r.ToOrg][r.FromOrg]++;
            });
            foreach (var td in todict.Keys)
            {
                StringBuilder tmp = new StringBuilder();
                int           cnt = 0;
                foreach (var fd in todict[td].Keys)
                {
                    tmp.Append(", " + fd.Name);
                    cnt += todict[td][fd];
                }
                toOrgReport.Append("\r\nTill " + td.Name + " (" + cnt + " st) från " + tmp.ToString().Substring(2));
            }


            string reportMessage = string.Format(
                "Result from running recommendation to change org mails:\r\n"
                + "Time:    {0,10:#0.0} minutes. \r\n"
                + "Checked: {1,10:g}\r\n"
                + "Sent:    {2,10:g}\r\n"
                + "Failed:  {3,10:g}\r\n",
                DateTime.Now.Subtract(starttime).TotalMinutes, processedCounter, sentCounter, failCounter)
                                   + fromOrgReport + "\r\n"
                                   + toOrgReport;

            BasicPersonRole[] UPSecretary = SwarmDb.GetDatabaseForReading().GetPeopleWithRoleType(RoleType.OrganizationSecretary,
                                                                                                  new int[] { Organization.UPSEid },
                                                                                                  new int[] { });
            if (UPSecretary.Length > 0)
            {
                Person.FromIdentity(UPSecretary[0].PersonId).SendOfficerNotice("ChangeOrg Mails Job report", reportMessage, Organization.UPSEid);
            }

            Person.FromIdentity(7838).SendOfficerNotice("ChangeOrgMails run", reportMessage, Organization.UPSEid);//Debug
        }