public Member(string[] data) { _data = data; _allocatedCompartment = null; _ListGroup = new List <Group>(); _exclude = false; }
/// <summary> /// 作業用区画作成 /// </summary> public void BuildWorkCompartment() { //現在保持しているリストを初期化 _ListWorkCompartment = new List<Compartment>(); //区画情報から作業用区画作成 for (int j = 1; j < _compartmentInfo.Rows.Count; j++) { string[] tmpCompartmentData = _compartmentInfo.Rows[j]; Compartment tmpCompartment = new Compartment(tmpCompartmentData); if (tmpCompartment.Name != "") { _ListWorkCompartment.Add(tmpCompartment); } } }
/// <summary> /// リストの中で最もメンバーの少ない部屋を探す /// </summary> /// <param name="listCompartment"></param> /// <returns></returns> private Compartment FindFewestMemberAllocatedCompartmentFromList(List <Compartment> listCompartment) { Compartment result = null; if (listCompartment.Count > 0) { Compartment min = listCompartment[0]; foreach (Compartment c in listCompartment) { if (min.MemberCount > c.MemberCount) { min = c; } } result = min; } return(result); }
/// <summary> /// 区画リストかすでに割り当てられている同じメンバーの区画を探す /// </summary> /// <param name="mem"></param> /// <param name="listCompartment"></param> /// <returns></returns> private Compartment GetAllocatedCompartment(AttendeeAllocator.Member mem, List <Compartment> listCompartment) { //すでに割り当てられていることがわかっている場合 if (mem.IsAllocated == true) { return(mem.AllocatedCompartment); } //不明な場合は区画リストから探し出す Compartment result = null; foreach (Compartment cmp in listCompartment) { if (cmp.IsInMember(mem) == true) { result = cmp; break; } } return(result); }
/// <summary> /// 割り当て後の区画データからCSVデータ作成 /// </summary> /// <param name="listCompartment"></param> public Layouter(List <Compartment> listCompartment, AttendeeInfo attInfo) { _listItem = new List <int>(); //名簿見出し行でレイアウトに使用する項目数 int layoutItems = FindItemFromAttendeeInfo(attInfo); //列数の算出 //最大の列数 = LayoutXの最大値 + 名簿見出しアイテム数 + 1 //行数の算出 //最大行数 = LayoutYの最大値 + LayaoutY最大値となる区画の最大収容人数 int max_x = 0; int max_y = 0; Compartment maxyCompartment = listCompartment[0]; foreach (Compartment c in listCompartment) { if (c.X > max_x) { max_x = c.X; } if ((c.Y + c.Max) > max_y) { max_y = c.Y + c.Max; maxyCompartment = c; } } max_x += layoutItems + 1;//+1は区画名が入るため //m_dgv = new DataGridView(); //m_dgv.RowCount = max_x; //m_dgv.ColumnCount = max_y; //CSVデータ用の文字列を空白で埋める _rows = new List <string[]>(); //見出し行の作成 string[] tmpRow = new string[max_x]; string[] attInfoTitle = attInfo.Rows[0]; //int topItems = FindTopItems(listCompartment); List <Compartment> listTopCompartment = FindTopCompartment(listCompartment); if (listTopCompartment.Count < 1) { //ERROR return; } int topItems = listTopCompartment.Count; foreach (Compartment c in listTopCompartment) // for (int i = 0; i < topItems; i++) { //int curBaseX = (_listItem.Count + 1) * i; int curBaseX = c.X; tmpRow[curBaseX] = "区画名"; for (int j = 0; j < _listItem.Count; j++) { string title; string tmpTitle = attInfoTitle[_listItem[j]]; if (tmpTitle[0] == '*') { title = tmpTitle.Remove(0, 1); } else { title = tmpTitle; } tmpRow[j + curBaseX + 1] = title; } } _rows.Add(tmpRow); //とりあえず空の行を作って埋める for (int i = 0; i < max_y; i++) { tmpRow = new string[max_x]; _rows.Add(tmpRow); } //区画毎に内容を埋めていく foreach (Compartment c in listCompartment) { for (int i = 0; i < c.MemberCount; i++) { tmpRow = _rows[c.Y + i + 1]; //+1は見出し行補正 tmpRow[0 + c.X] = c.Name; Member mem = c.ListMember[i]; for (int j = 0; j < _listItem.Count; j++) { tmpRow[0 + c.X + j + 1] = mem.Data[_listItem[j]]; //+1は区画名補正 } //内容反映 _rows[c.Y + i + 1] = tmpRow;//+1は見出し行補正 } } }
/// <summary> /// 条件に最も近い区画をリストから探す /// </summary> /// <param name="listCompartment"></param> /// <param name="number"></param> /// <returns></returns> private Compartment GetMatchCompartment(List <Compartment> listCompartment, int number) { Compartment mostNearSpaceCompartmentL = null; Compartment mostNearSpaceCompartmentS = null; foreach (Compartment cmp in listCompartment) { //必要とする空きと一致する区画が見つかった場合 if (cmp.RemainSpace == number) { //この区画に排他属性の他のグループのメンバーが割り当てられていないか確認 if (cmp.IsAlreadyAllocatedExclusiveGroupMenber(this, null) == false) { //そういう人は居なかった return(cmp); } } else { //必要とする空きとの差が一番近い区画を覚えておく //空き人数の方が必要とするメンバー数を上回っている部屋の記憶 int diff = cmp.RemainSpace - number; if (diff > 0) { if (mostNearSpaceCompartmentL == null) { mostNearSpaceCompartmentL = cmp; } else { if ((mostNearSpaceCompartmentL.RemainSpace - number) > diff) { mostNearSpaceCompartmentL = cmp; } } } else { //とにかく一番空き人数が近い部屋の記憶 if (mostNearSpaceCompartmentS == null) { mostNearSpaceCompartmentS = cmp; } else { int diffAbs = Math.Abs(cmp.RemainSpace - number); if (Math.Abs(mostNearSpaceCompartmentS.RemainSpace - number) > diffAbs) { mostNearSpaceCompartmentS = cmp; } } } } } if (mostNearSpaceCompartmentL != null) { return(mostNearSpaceCompartmentL); } else { return(mostNearSpaceCompartmentS); } }
/// <summary> /// メンバーを区画へ割り当てる /// </summary> /// <param name="listCompartment"></param> /// <returns></returns> public bool AllocateMemberToCompartment(List <Compartment> listCompartment) { bool result = true; //================================================= //グループ属性に「除外」がある場合 //================================================= //割り当てしない if (_exclude == true) { return(true); } //================================================= //割り当ての準備 //================================================= //優先設定されている部屋のリストを作る List <Compartment> listPriorityCompartment = listCompartment.Where(c => c.PriorityGroup == _groupName).ToList(); listPriorityCompartment = listCompartment.Where(c => c.PriorityGroup == _groupName).ToList(); //優先設定されていない部屋のリストを作る List <Compartment> listNormalCompartment = listCompartment.Where(c => c.PriorityGroup == "").ToList(); //割り当てなければいけないメンバーのリストを作成 //List<Member> listRemainMembers = new List<Member>(); List <Member> listRemainMembers = _members.Where(m => m.IsAllocated != true).ToList(); //foreach (Member member in _members) //{ // listRemainMembers.Add(member); //} int remainMemberCount = listRemainMembers.Count; //================================================= //グループ属性に「集合」がある場合 //================================================= if (_gather == true) { //まずは優先設定されている部屋への割り当てを試みる AllocatePriorityCompartmentGather(listPriorityCompartment, listRemainMembers); //優先設定区画割り当て後の残りの未割り当てメンバーを算出 remainMemberCount = GetNotAllocatedRemainmemberCount(listRemainMembers); //通常区画の最大空き人数を算出 if (remainMemberCount > 0) { int normalCompartmentMaxRemainSpace = GetNumberOfMaxSpace(listNormalCompartment); int moreNeed = remainMemberCount - normalCompartmentMaxRemainSpace; if (moreNeed > 0) { _errorMessages.Add(string.Format("[エラー]グループ[{0}]用の{1}人分の区画がありませんでした。", this.Name, remainMemberCount)); } else { moreNeed = 0; } //未割り当てメンバーがいなくなるまで(または、収容可能最大人数に達するまで)マッチする部屋へ割り当てる int maxLoop = remainMemberCount; for (int i = 0; i < maxLoop; i++) { if (remainMemberCount > 0) { Compartment matchCompartment = GetMatchCompartment(listNormalCompartment, remainMemberCount); foreach (Member mem in listRemainMembers) { if (mem.IsAllocated == false) { matchCompartment.AllocateExclusiveMember(mem, this); mem.AllocatedCompartment = matchCompartment; } } remainMemberCount = GetNotAllocatedRemainmemberCount(listRemainMembers); } else { break; } } } } //================================================= //グループ属性に「分散」がある場合 //================================================= else if (_scatter == true) { //まずは優先設定されている部屋への割り当てを試みる AllocatePriorityCompartmentScatter(listPriorityCompartment, listRemainMembers); //普通の部屋の中から割り当られているメンバーが最小かつ、排他グループがいない部屋を探す AllocatePriorityCompartmentScatter(listNormalCompartment, listRemainMembers); //未割り当ての人が居るならエラー remainMemberCount = GetNotAllocatedRemainmemberCount(listRemainMembers); if (remainMemberCount > 0) { foreach (Member m in listRemainMembers) { if (m.IsAllocated == false) { _errorMessages.Add(string.Format("[エラー]グループ{0}に所属するキーコード{1}を割り当てる事ができませんでした。", _groupName, m.Key)); } } } } //================================================= //グループ属性が無い場合(いまのところ分散と同じ方法で割り当て) //================================================= else { //まずは優先設定されている部屋への割り当てを試みる //AllocatePriorityCompartmentScatter(listPriorityCompartment, listRemainMembers); AllocatePriorityCompartmentGather(listPriorityCompartment, listRemainMembers); //普通の部屋の中から割り当られているメンバーが最小かつ、排他グループがいない部屋を探す AllocatePriorityCompartmentScatter(listNormalCompartment, listRemainMembers); //どこでもいいから開いている(排他グループのメンバーがいない)開いている部屋をさがす AllocateCompartment(listNormalCompartment, listRemainMembers); //未割り当ての人が居るならエラー remainMemberCount = GetNotAllocatedRemainmemberCount(listRemainMembers); if (remainMemberCount > 0) { foreach (Member m in listRemainMembers) { if (m.IsAllocated == false) { _errorMessages.Add(string.Format("[エラー]グループ{0}に所属するキーコード{1}を割り当てる事ができませんでした。", _groupName, m.Key)); } } } } return(result); }