// // LevelGenerate.cpp // auto_fill_jewel_v3 // // Created by Red on 2024/11/23. // #include "LevelGenerate.hpp" #include #include #include #include "FillGlobalConfig.hpp" #include #include "BoxPositionTool.hpp" #include "GridPositionTool.hpp" #include "LevelThumbTool.hpp" #define MOVEID_NO_MOVE 0 #define MOVEID_1ST_LINE 1 #define MOVEID_2ND_LINE 2 using namespace std; void LevelGenerate::generateAll(FillGlobalConfig::LevelData levelData, string outname) { cout<<"debug level "<clearGridBoxFilledStatus() ;//每次填充盘子前必须清空盘子占位情况 vector resultPlateFRs ; vector resultPlateCenterPosiArr ; generate(levelData, false, nullptr , resultPlateFRs, resultPlateCenterPosiArr) ; //输出结果 string pngName0 = outname + "_000000.png" ; LevelThumbTool ltt ; ltt.makeThumb3(pngName0, resultPlateFRs, resultPlateCenterPosiArr) ; //对于所有移动的配置 vector mmcArr = fgc->getAllMoveConfigByJewels(levelData) ; for(int im=0;im < mmcArr.size();++ im ) { string moveName = mmcArr[im]._first->_type ; if( mmcArr[im]._second ) moveName += mmcArr[im]._second->_type ; else moveName += "00" ; cout<<"debug moveName "<clearGridBoxFilledStatus() ;//每次填充盘子前必须清空盘子占位情况 vector resultPlateFRs1 ; vector resultPlateCenterPosiArr1 ; generate(levelData, true, &mmcArr[im] , resultPlateFRs1, resultPlateCenterPosiArr1) ; //输出结果 string pngName1 = outname + "_" + moveName; pngName1 += ".png" ; ltt.makeThumb3(pngName1, resultPlateFRs1, resultPlateCenterPosiArr1) ; } } bool LevelGenerate::generate( FillGlobalConfig::LevelData levelData, const bool isMovable, const FillGlobalConfig::MultiMoveConfig* mulMoveConfig , //移动盘子配置,如果isMovable为false,这个参数忽略,可以传入nullptr vector& resultPlateFillResults, vector& resultPlateCenterPointArr ) { resultPlateFillResults.clear() ; resultPlateCenterPointArr.clear() ; auto ms0 = std::chrono::system_clock::now().time_since_epoch() ; uint64_t ms00 = std::chrono::duration_cast(ms0).count() ; srand(_seed); unordered_map > jewIdSzCntStorageMap ;// unordered_map<宝石ID,tuple<尺寸,库存数量> > FillGlobalConfig* fgc = FillGlobalConfig::getInstance() ; int bigJewelCnt = 0 ; int midJewelCnt = 0; int smlJewelCnt = 0 ; for(int ij = 0 ; ij < levelData._jewelIds.size();++ ij ) { int jewId = levelData._jewelIds[ij] ; int cnt = levelData._cnts[ij] ; FillGlobalConfig::JewelItem* jewItem = fgc->getJewelItemById(jewId) ; jewIdSzCntStorageMap[jewId] = {jewItem->_size,cnt} ; if( jewItem->_size == FILLGLOBALCONFIG_JEWELSIZE_SM ) { smlJewelCnt+=cnt ; }else if( jewItem->_size == FILLGLOBALCONFIG_JEWELSIZE_MD ) { midJewelCnt += cnt ; }else if( jewItem->_size == FILLGLOBALCONFIG_JEWELSIZE_LG ) { bigJewelCnt += cnt ; } } //每个盘子类型小号宝石承载量 //按顺序分别为大和中 FillGlobalConfig::PlateItem* bigPlateH = fgc->getPlateItemBySzNDirection(FILLGLOBALCONFIG_PLATESIZE_LG, 1) ; FillGlobalConfig::PlateItem* midPlateH = fgc->getPlateItemBySzNDirection(FILLGLOBALCONFIG_PLATESIZE_MD, 1) ; FillGlobalConfig::PlateItem* bigPlateV = fgc->getPlateItemBySzNDirection(FILLGLOBALCONFIG_PLATESIZE_LG, 0) ; FillGlobalConfig::PlateItem* midPlateV = fgc->getPlateItemBySzNDirection(FILLGLOBALCONFIG_PLATESIZE_MD, 0) ; //FillGlobalConfig::PlateItem* smlPlate = fgc->getPlateItemBySzNIndex(FILLGLOBALCONFIG_PLATESIZE_SM, 0) ; vector usedPlates = {bigPlateH,midPlateH,bigPlateV,midPlateV} ;//{bigPlate,midPlate,smlPlate} ; int maxSmlJewCapPerPlate = 0; int minSmlJewCapPerPlate = 99999 ; for(int ip=0;ip_bigJewCap*4 , maxSmlJewCapPerPlate) ; minSmlJewCapPerPlate = fmin( usedPlates[ip]->_bigJewCap*4 , minSmlJewCapPerPlate) ; } //等效小宝石数量 int effSmallJewelsCount = bigJewelCnt*4 + midJewelCnt*2 + smlJewelCnt ; //cout<<"bigJewelCnt "< resPlateNLyrCnt = generatePlateTypeAndLayerCnts2(isMovable, mulMoveConfig, levelData._difficulty,effSmallJewelsCount); if( resPlateNLyrCnt.size()==0 ) { //cout<<"failed at generatePlateTypeAndLayerCnts"<_layerCnt) ; //对每个盘子组合进行填充宝石 RandomGridFiller filler ; filler._seed = this->_seed ; srand(filler._seed); //构建每个盘子每个层的填充结果容器 vector< tuple,int> > plateIdLyrFillResultsMoveIdArray ;// tuple //从顶到底部,逐层进行填充 int residues = 0 ; for(int nlayer = maxLyrCnt; nlayer > 0 ; nlayer-- ) { //cout<<"for layer "< plateIdArr ;//临时符合当前层次的盘子类型ID vector moveIdArr ;//临时保存对应盘子是否是可移动的,0-不可移动,1-第一移动行,2-第二移动行 for(auto it = resPlateNLyrCnt.begin();it!=resPlateNLyrCnt.end();++it ) { if(it->_layerCnt>=nlayer) { plateIdArr.push_back(it->_plateId) ; moveIdArr.push_back( it->_moveId ) ; } } //该层总计需要填充多少小宝石 int currLyrNeedEquvSmlCnt = 0 ; for(int ip=0;ipgetPlateItemById(plateIdArr[ip])->_bigJewCap*4 ; } //cout<<"layer need eqsmCnt "< chosenJewIdNCnt = randPickJewels(currLyrNeedEquvSmlCnt, solPercent, jewIdSzCntStorageMap) ; int choseEqSmCnt=0; for(auto itp=chosenJewIdNCnt.begin();itp!=chosenJewIdNCnt.end();++itp) { choseEqSmCnt += jewSz2SmlCnt( fgc->getJewelItemById(itp->first)->_size) * itp->second ; } //cout<<"layer choose eqsmCnt "< fr = fillPlateOneLayer(filler, plateId1 , chosenJewIdNCnt) ; tuple,int> plateLyrFillResult={plateId1 , nlayer , fr , moveId1 } ; plateIdLyrFillResultsMoveIdArray.push_back(plateLyrFillResult); } //检查为该层挑选的宝石是不是全部填完了,如果没有填完还要还给库存,给下一轮填充用 residues = 0 ; for(auto itjn = chosenJewIdNCnt.begin();itjn!=chosenJewIdNCnt.end();++itjn){ if( itjn->second>0 ) { residues+=itjn->second; std::get<1>(jewIdSzCntStorageMap[itjn->first]) += itjn->second ;//剩余的加回到库存里 } } //cout<<"layer chosen jewels residues "<0 ) { int extraPlateCnt = 0 ; //剩了,添加一个小盘子和层,仍然剩了再继续加盘子加层 unordered_map residueJewIdAndCnts = findUnfilledInStorages(jewIdSzCntStorageMap) ; while( residueJewIdAndCnts.size()>0 ) { //新建一个中盘子 extraPlateCnt++; //cout<<"add extra plate "<< extraPlateCnt <_id ; for(int ilyr = 1 ; ilyr <= maxLyrCnt; ++ ilyr ) { vector frs = fillPlateOneLayer(filler, plateId, residueJewIdAndCnts) ; plateIdLyrFillResultsMoveIdArray.push_back( {plateId,ilyr,frs, MOVEID_NO_MOVE } ); //cout<<"add extra lyr "<(ms1).count() ; //cout<<"duration "< LevelGenerate::generatePlateTypeAndLayerCnts(const int difficulty,const int totEquvSmallJewelCnt) { vector results ; //... //... return results ; } //考虑可移动关卡的条件 vector LevelGenerate::generatePlateTypeAndLayerCnts2( const bool isMovable, const FillGlobalConfig::MultiMoveConfig* mulMoveConfig, const int difficulty, const int totEquvSmallJewelCnt ) { //如果是移动关卡,那么至少需要保证如下等价小盘子数量,如果减少层数仍然不能满足那么就有几个盘子输出几个 //const int MAX_LG_PLATE_CNT = 9 ;// + (isMovable?1:0) ; // const int MAX_SM_PLATE_CNT = MAX_LG_PLATE_CNT*4 ; //const int MAX_SM_JEWEL_CNT_PER_LAYER = MAX_LG_PLATE_CNT * 24 ; const int MID_PLATE_CAP = 12 ;//中盘子对小宝石的容量 //const int minEquaSmPlateCntForMovable = 16 ; // //const int smPlateEquaSmJewelCnt = 6 ;// 小盘子装1.5个大,3个中,6个小 //一个关卡最多出现大、中、小盘子个数 int tempBigPlateCnt1 = 9 ;// 1个大盘子=2两个中盘子 int tempMidPlateCnt1 = 0 ; computePlateCount(mulMoveConfig, tempBigPlateCnt1, tempMidPlateCnt1) ; int midPlateMaxCnt = tempBigPlateCnt1 * 2 + tempMidPlateCnt1 ;//大盘子数量换算成中盘子 FillGlobalConfig* fgc = FillGlobalConfig::getInstance() ; FillGlobalConfig::PlateItem* bigPlateH = fgc->getPlateItemBySzNDirection(FILLGLOBALCONFIG_PLATESIZE_LG, 1) ; FillGlobalConfig::PlateItem* midPlateH = fgc->getPlateItemBySzNDirection(FILLGLOBALCONFIG_PLATESIZE_MD, 1) ; FillGlobalConfig::PlateItem* bigPlateV = fgc->getPlateItemBySzNDirection(FILLGLOBALCONFIG_PLATESIZE_LG, 0) ; FillGlobalConfig::PlateItem* midPlateV = fgc->getPlateItemBySzNDirection(FILLGLOBALCONFIG_PLATESIZE_MD, 0) ; //如果是移动关卡,先构建移动盘子 int totEquvSmallJewelCnt2 = totEquvSmallJewelCnt ; vector results ; //剩余可以用的中盘子个数 if( isMovable ) { int residueEquvSmlJewelCnt = 0 ; results = generatePlateTypeAndLayerCntsForMovablePlates(mulMoveConfig, totEquvSmallJewelCnt2, residueEquvSmlJewelCnt) ; totEquvSmallJewelCnt2 = residueEquvSmlJewelCnt ; //减去移动的盘子 for(int ir = 0 ; ir < results.size(); ++ ir ){ if( fgc->getPlateItemById(results[ir]._plateId)->_size == FILLGLOBALCONFIG_PLATESIZE_LG ) { midPlateMaxCnt-=2 ;//减去移动的盘子 }else if(fgc->getPlateItemById(results[ir]._plateId)->_size == FILLGLOBALCONFIG_PLATESIZE_MD) { midPlateMaxCnt-=1 ;//减去移动的盘子 } } } int equvMidPlateCnt = ceil( totEquvSmallJewelCnt2 * 1.0 / MID_PLATE_CAP) ; // 本关需要多少个一层中盘子的总数量 int layerCnt0 = 1 ;//盘子层数下限 int layerCnt1 = 1 ;//盘子层数上限 //计算可能的层取值范围 { layerCnt0 = fmax(1 , totEquvSmallJewelCnt2 / (midPlateMaxCnt*MID_PLATE_CAP) ) ; if( layerCnt0<3 ) layerCnt1 = 3 ; else layerCnt1 = layerCnt0 + 1 ; } int bigPlateCnt0 = totEquvSmallJewelCnt2 * 1.0 / layerCnt1 / 24 ; //大盘子最少需要数量 int bigPlateCnt1 = totEquvSmallJewelCnt2 * 1.0 / layerCnt0 / 24 + 1; //大盘子最多需要数量 int midPlateCnt0 = bigPlateCnt0*2 ; int midPlateCnt1 = bigPlateCnt1*2 ; bigPlateCnt1 = fmin( midPlateMaxCnt/2 ,bigPlateCnt1 ) ; midPlateCnt1 = fmin( midPlateMaxCnt ,midPlateCnt1 ) ; bool findFirstAvailableComb = false ;//第一个完全放入宝石的组合,用于当不满足任何条件时,至少返回一个可装入全部宝石的默认方案 vector> possibleResults ;//满足全部百分比要求的组合 vector firstAvailablePlateComb ;//第一个满足全部宝石填充的组合,如果需要移动还要考虑最小移动盘子个数的条件 int firstAvailableLyrCnt = 0 ; //难度对盘子数量的限制 普通 难 极难 vector< vector > hardPlateCntPercent0 = { {0.3,0.3}, {0.2,0.4}, {0.1,0.5} } ; vector< vector > hardPlateCntPercent1 = { {0.7,0.7}, {0.6,0.8}, {0.5,0.9} } ; //穷举全部盘子和层的组合找到符合条件的组合 for(int ibig = 0; ibig <= bigPlateCnt1; ++ ibig ) { for(int imid = 0; imid <= midPlateCnt1 ; ++ imid ) { int currEquvMidPlateCnt = imid+ibig*2 ; if( currEquvMidPlateCnt==0 || currEquvMidPlateCnt > midPlateMaxCnt ) continue ; float bigPlateCntPercent = ibig*2.0 / currEquvMidPlateCnt ; float midPlateCntPercent = imid*1.0 / currEquvMidPlateCnt ; vector percentArr = {bigPlateCntPercent,midPlateCntPercent} ; //判断每个盘子百分比是否满足难度要求 bool percentOk = true ; for(int iplatetype=0;iplatetypepercentArr[iplatetype] || hardPlateCntPercent1[difficulty][iplatetype]3 ) ) { //保证至少有一个可以满足宝石的盘子组合,优先保存总层数大于3的情况 //当前盘子组合下最小满足的层数 int upperLyrCnt = ceil( totEquvSmallJewelCnt2 * 1.0 / (currEquvMidPlateCnt*MID_PLATE_CAP) ) ; bool upperLyrCntOk = true ; if( findFirstAvailableComb ) { if( upperLyrCnt >= firstAvailableLyrCnt ) { upperLyrCntOk = false ; } } vector pidArr ; vector capArr ; vector lyrArr ; //根据需求文档,非移动盘子,大盘子只用竖的,中盘子只用横的。 for(int it=0;it_id);capArr.push_back(bigPlateV->_bigJewCap*4); lyrArr.push_back(upperLyrCnt); } for(int it=0;it_id);capArr.push_back(midPlateH->_bigJewCap*4); lyrArr.push_back(upperLyrCnt); } bool lyrOk = isJustFilledAll2(capArr, lyrArr, totEquvSmallJewelCnt2) ; if( lyrOk==false && upperLyrCnt>1 ) { for(int it=0;it pidArr ; vector capArr ; vector lyrArr ; //根据需求文档,非移动盘子,大盘子只用竖的,中盘子只用横的。 for(int it=0;it_id);capArr.push_back(bigPlateV->_bigJewCap*4); lyrArr.push_back(2); } for(int it=0;it_id);capArr.push_back(midPlateH->_bigJewCap*4); lyrArr.push_back(2); } bool lyrOk = isJustFilledAll2(capArr, lyrArr, totEquvSmallJewelCnt2) ; if(!lyrOk) continue; //保存结果 vector tres(capArr.size()) ; for(int it = 0 ; it < capArr.size(); ++ it ) { tres[it]._plateId = pidArr[it] ; tres[it]._layerCnt = lyrArr[it] ; tres[it]._moveId = MOVEID_NO_MOVE ;//不会移动的盘子 } possibleResults.push_back(tres) ; }else if( difficulty==FILLGLOBALCONFIG_DIFFCULTY_HARD2 ) { //全部3层 vector pidArr ; vector capArr ; vector lyrArr ; //根据需求文档,非移动盘子,大盘子只用竖的,中盘子只用横的。 for(int it=0;it_id);capArr.push_back(bigPlateV->_bigJewCap*4); lyrArr.push_back(3); } for(int it=0;it_id);capArr.push_back(midPlateH->_bigJewCap*4); lyrArr.push_back(3); } //cout<<"debug big "< tres(capArr.size()) ; for(int it = 0 ; it < capArr.size(); ++ it ) { tres[it]._plateId = pidArr[it] ; tres[it]._layerCnt = lyrArr[it] ; tres[it]._moveId = MOVEID_NO_MOVE ;//不会移动的盘子 } possibleResults.push_back(tres) ; }else{ //50% 2层, 50% 3层 vector pidArr ; vector capArr ; vector lyrArr ; //根据需求文档,非移动盘子,大盘子只用竖的,中盘子只用横的。 for(int it=0;it_id);capArr.push_back(bigPlateV->_bigJewCap*4); lyrArr.push_back((rand()%2==0)?2:3); } for(int it=0;it_id);capArr.push_back(midPlateH->_bigJewCap*4); lyrArr.push_back((rand()%2==0)?2:3); } bool lyrOk = isJustFilledAll2(capArr, lyrArr, totEquvSmallJewelCnt2) ; if(!lyrOk) continue; //保存结果 vector tres(capArr.size()) ; for(int it = 0 ; it < capArr.size(); ++ it ) { tres[it]._plateId = pidArr[it] ; tres[it]._layerCnt = lyrArr[it] ; tres[it]._moveId = MOVEID_NO_MOVE ;//不会移动的盘子 } possibleResults.push_back(tres) ; } } } //随机挑选一个结果返回 if( possibleResults.size()> 0 ) { int randindex = rand() % possibleResults.size(); for(int ip = 0 ; ip < possibleResults[randindex].size();++ ip ) { results.push_back(possibleResults[randindex][ip]) ; } }else { for(int ip = 0 ; ip < firstAvailablePlateComb.size();++ ip ) { results.push_back(firstAvailablePlateComb[ip]) ; } } return results ;// } //随机排序数组索引值 vector LevelGenerate::randIndices(const int count0 ) { int count = count0 ; vector indices ; unordered_map dict ; while( count > 0 ) { int r = rand()%count0; if( dict.find(r) == dict.end() ) { dict[r] = true ; indices.push_back(r) ; count-- ; } } return indices; } bool LevelGenerate::isJustFilledAll2( const vector& plateCaps,//每个盘子的容量 const vector eachPlateLyrCnt,//对应盘子的层数 const int totSmlJewCnt ) { assert(plateCaps.size()>0); assert(plateCaps.size()==eachPlateLyrCnt.size()); int fillcnt1 = 0; for(int ip = 0 ;ip LevelGenerate::randPickJewels( const int needEquvSmlCnt,const float solvedPercent, unordered_map>& jewStorages ) { int needEquvSmlCnt2 = needEquvSmlCnt ; int storageEquvSmlCnt = 0 ; int storageJewTypeCnt = jewStorages.size() ; for(auto it=jewStorages.begin();it!=jewStorages.end();++it) storageEquvSmlCnt+= std::get<1>(it->second)*jewSz2SmlCnt(std::get<0>(it->second)) ; unordered_map res ; const float solPer = fmax(0.0,fmin(solvedPercent,1.0f)) ; //首先尝试可解的百分比部分 int solEqSmGrpCnt = needEquvSmlCnt*solPer/3 ; // 随机尝试solEqSmGrpCnt*2 次取宝石,每次取一组。 int loopCnt=solEqSmGrpCnt*storageJewTypeCnt*10;//随机迭代数量加大10倍,避免有始终选不到的情况 while( solEqSmGrpCnt> 0 && storageEquvSmlCnt>0 && loopCnt>0) { int randJewI = rand()%storageJewTypeCnt ; auto itjew = jewStorages.begin() ; std::advance(itjew, randJewI) ; int jid = itjew->first ; int storage1 = std::get<1>( itjew->second ) ; int oneGrpEqSmGrpCnt = jewSz2SmlCnt( std::get<0>(itjew->second) ) ; if( storage1>=3 && oneGrpEqSmGrpCnt<=solEqSmGrpCnt ) { //库存有,且满足所需可解组数 std::get<1>(itjew->second)-=3 ; solEqSmGrpCnt -= oneGrpEqSmGrpCnt ; storageEquvSmlCnt -= oneGrpEqSmGrpCnt*3 ; needEquvSmlCnt2 -= oneGrpEqSmGrpCnt*3 ; //本次所需的剩余等效小宝石个数 res[jid] += 3 ; } --loopCnt ; } //尝试剩余百分比和上一步剩余没有符合条件的个数 loopCnt = needEquvSmlCnt2*storageJewTypeCnt ; int jindex = 0 ; while( loopCnt>0 && needEquvSmlCnt2> 0 && storageEquvSmlCnt>0 ) { auto itjew = jewStorages.begin() ; std::advance(itjew, jindex) ; int jid = itjew->first; int sz = std::get<0>(itjew->second) ; int stor = std::get<1>(itjew->second) ; int eqsmCnt = jewSz2SmlCnt(sz) ; if( stor>0 && eqsmCnt <= needEquvSmlCnt2 ) { std::get<1>(itjew->second)-=1 ; needEquvSmlCnt2-=eqsmCnt ; storageEquvSmlCnt-=eqsmCnt ; res[jid] += 1 ; } ++jindex ; if(jindex>=storageJewTypeCnt) jindex=0;//循环取之,直到本层所需全部取完 --loopCnt; } return res ; } int LevelGenerate::jewSz2SmlCnt(int sz) { switch (sz) { case FILLGLOBALCONFIG_JEWELSIZE_LG: return 4;break; case FILLGLOBALCONFIG_JEWELSIZE_MD: return 2;break; default: return 1;break; } return 1; } vector LevelGenerate::fillPlateOneLayer(RandomGridFiller& filler,const int plateId, unordered_map& jewStoragesForUse ) { auto fgc = FillGlobalConfig::getInstance() ; vector jewBoxArray ; FillGlobalConfig::PlateItem* pl = FillGlobalConfig::getInstance()->getPlateItemById(plateId) ; int plateEqSmCap = pl->_bigJewCap*4 ; int jewTypeCnt = jewStoragesForUse.size() ; int eqSmStorageCnt = 0 ; for(auto it = jewStoragesForUse.begin();it!=jewStoragesForUse.end();++it) { int jewEqSmCnt = jewSz2SmlCnt( fgc->getJewelItemById(it->first)->_size ); eqSmStorageCnt+=it->second*jewEqSmCnt ; } static int s_debug_cnt = 0; //cout<<"debug "<< s_debug_cnt << " storage eqsm count "< jewForPlateMap ;// int loopCnt = plateEqSmCap*jewTypeCnt*4;// 随机数量多给4倍 while(plateEqSmCap>0 && eqSmStorageCnt>0 && loopCnt>0 ) { int radv = rand() % jewTypeCnt ; auto it = jewStoragesForUse.begin() ; std::advance(it, radv) ; int jewEqSmCnt = jewSz2SmlCnt( fgc->getJewelItemById(it->first)->_size ); if( it->second>0 ) { if( jewEqSmCnt <= plateEqSmCap ) { plateEqSmCap -= jewEqSmCnt ; it->second -=1 ; eqSmStorageCnt -= jewEqSmCnt ; jewForPlateMap[it->first] += 1 ; if( it->second== 0 ) { jewStoragesForUse.erase(it) ; jewTypeCnt-- ; } } }else{ jewStoragesForUse.erase(it) ; jewTypeCnt-- ; } --loopCnt ; } //cout<<"debug "<< s_debug_cnt ++ <<" storage eqsm count "<second ; jbox._jewelTypeId = it->first ; jbox._width = fgc->getJewelItemById(it->first)->_bbWidth ; jbox._height = fgc->getJewelItemById(it->first)->_bbHeight ; jewBoxArray.push_back(jbox) ; } vector fillresults ; filler.fill(jewBoxArray, pl->_blx, pl->_bly, pl->_trx, pl->_try, fillresults) ; return fillresults ; } unordered_map LevelGenerate::findUnfilledInStorages( unordered_map>& jewStorages) { unordered_map res ; for(auto itj = jewStorages.begin();itj!=jewStorages.end();++itj) { int stor = std::get<1>(itj->second) ; int jid = itj->first ; if( stor>0 ) { res[jid] = stor ; std::get<1>(itj->second) = 0 ; } } return res ; } void LevelGenerate::regroupPlateLyrFillResults( vector,int>>& pidlyrFillMvidArray, vector& results) { int currLayer = 1 ;//从底层到顶层构建结果数据结构 int num = pidlyrFillMvidArray.size() ; int nloop = num ; while( nloop > 0 ) { //cout<<"regroup for layer "<( *itlyr ) ; int lyr = std::get<1>( *itlyr ) ; vector& frs = std::get<2>(*itlyr) ; int moveId = std::get<3>(*itlyr) ; if(pid>=0) { if( lyr==currLayer ) { if( lyr==1 ) { vector> frArr = {frs} ; PlateFillResult pfr ; pfr._layersFillResults = frArr ; pfr._moveId = moveId ; pfr._plateTypeId = pid ; results.push_back( pfr ) ; num-- ; std::get<0>( *itlyr ) = -1 ; }else { for(auto itPfr = results.begin();itPfr!=results.end();++itPfr ) { int pidr = itPfr->_plateTypeId ; int mvid = itPfr->_moveId ; vector>& frArr = itPfr->_layersFillResults ; if( pidr == pid && mvid == moveId && frArr.size()==currLayer-1 ) { frArr.push_back(frs); num-- ; std::get<0>( *itlyr ) = -1 ; break ; } } } } } } currLayer++ ; if( num==0 ) break ; nloop--; } //cout<<"last plate lyr num "<& plateFRArr, vector& resultPlateCenterPointArr ) { GridPositionTool gpt ; vector plateIdArr ; vector moveIdArr ; for(int ip = 0 ; ip < plateFRArr.size(); ++ ip ) { plateIdArr.push_back( plateFRArr[ip]._plateTypeId ) ; moveIdArr.push_back( plateFRArr[ip]._moveId ) ; } vector> resPosis ; string firstMoveTypeCode = "" ; string secondMoveTypeCode = "" ; if( movable ) { firstMoveTypeCode = mulMoveConfig->_first->_type[0] ; if( mulMoveConfig->_second ) secondMoveTypeCode = mulMoveConfig->_second->_type[0] ; } gpt.solve(movable, firstMoveTypeCode , secondMoveTypeCode, plateIdArr, moveIdArr, resPosis //这里结果是盘子左下角坐标,下面需要转换成中心坐标。 ) ; for(int ip=0;ipgetPlateItemById(plateIdArr[ip]) ; resultPlateCenterPointArr.push_back( { (float)resPosis[ip][0]+platePtr->_bbwid/2 , (float)resPosis[ip][1]+platePtr->_bbhei/2} ) ; } } vector LevelGenerate::generatePlateTypeAndLayerCntsForMovablePlates( const FillGlobalConfig::MultiMoveConfig* mulMoveConfig, const int totEquvSmallJewelCnt, int& retResidueEquvSmlJewelCnt ) { vector results ; retResidueEquvSmlJewelCnt = totEquvSmallJewelCnt ; FillGlobalConfig* fgc = FillGlobalConfig::getInstance() ; FillGlobalConfig::PlateItem* bigPlateH = fgc->getPlateItemBySzNDirection(FILLGLOBALCONFIG_PLATESIZE_LG, 1) ; FillGlobalConfig::PlateItem* midPlateH = fgc->getPlateItemBySzNDirection(FILLGLOBALCONFIG_PLATESIZE_MD, 1) ; FillGlobalConfig::PlateItem* bigPlateV = fgc->getPlateItemBySzNDirection(FILLGLOBALCONFIG_PLATESIZE_LG, 0) ; FillGlobalConfig::PlateItem* midPlateV = fgc->getPlateItemBySzNDirection(FILLGLOBALCONFIG_PLATESIZE_MD, 0) ; const int MAX_MOVE_CONFIG_CNT = 2; FillGlobalConfig::MoveConfig* arr[MAX_MOVE_CONFIG_CNT] = { mulMoveConfig->_first , mulMoveConfig->_second } ; for(int ii = 0 ; ii < MAX_MOVE_CONFIG_CNT ; ++ ii ) { FillGlobalConfig::MoveConfig* moveConfig = arr[ii] ; if( moveConfig==nullptr ) continue ; //中盘子横 for(int imid = 0 ; imid < moveConfig->_midPlateCntH ; ++ imid ) { PlateIdAndLayerCnt palc ; palc._layerCnt = moveConfig->_nLayer ; palc._plateId = midPlateH->_id ; palc._moveId = ii+1 ;//第一行为1,第二行为2 results.push_back(palc) ; retResidueEquvSmlJewelCnt -= midPlateH->_bigJewCap*4*palc._layerCnt ; } //中盘子竖 for(int imid = 0 ; imid < moveConfig->_midPlateCntV ; ++ imid ) { PlateIdAndLayerCnt palc ; palc._layerCnt = moveConfig->_nLayer ; palc._plateId = midPlateV->_id ; palc._moveId = ii+1 ; results.push_back(palc) ; retResidueEquvSmlJewelCnt -= midPlateV->_bigJewCap*4*palc._layerCnt ; } //大盘子横 for(int ibig = 0 ; ibig < moveConfig->_bigPlateCntH ; ++ ibig ) { PlateIdAndLayerCnt palc ; palc._layerCnt = moveConfig->_nLayer ; palc._plateId = bigPlateH->_id ; palc._moveId = ii+1 ; results.push_back(palc) ; retResidueEquvSmlJewelCnt -= bigPlateH->_bigJewCap*4*palc._layerCnt ; } //大盘子竖 for(int ibig = 0 ; ibig < moveConfig->_bigPlateCntV ; ++ ibig ) { PlateIdAndLayerCnt palc ; palc._layerCnt = moveConfig->_nLayer ; palc._plateId = bigPlateV->_id ; palc._moveId = ii+1 ; results.push_back(palc) ; retResidueEquvSmlJewelCnt -= bigPlateV->_bigJewCap*4*palc._layerCnt ; } } return results ; } void LevelGenerate::computePlateCount(const FillGlobalConfig::MultiMoveConfig* mmc ,int& retBigPlateCnt, int& retMidPlateCnt ) { if( mmc==nullptr ) { retBigPlateCnt = 9 ; retMidPlateCnt = 0 ; }else if( mmc->_first && mmc->_second ) { if( mmc->_first->_type.find("A") != string::npos && mmc->_second->_type.find("A") != string::npos ) { retBigPlateCnt = 6 ; retMidPlateCnt = 8 ; }else if( mmc->_first->_type.find("B") != string::npos && mmc->_second->_type.find("B") != string::npos ) { retBigPlateCnt = 9 ; retMidPlateCnt = 0 ; }else if( mmc->_first->_type.find("C") != string::npos && mmc->_second->_type.find("C") != string::npos ) { retBigPlateCnt = 11 ; retMidPlateCnt = 0 ; }else if( mmc->_first->_type.find("B") != string::npos && mmc->_second->_type.find("A") != string::npos) { retBigPlateCnt = 6 ; retMidPlateCnt = 7 ; }else if( mmc->_first->_type.find("C") != string::npos && mmc->_second->_type.find("B") != string::npos ) { retBigPlateCnt = 10 ; retMidPlateCnt = 0 ; }else if( mmc->_first->_type.find("C") != string::npos && mmc->_second->_type.find("A") != string::npos ) { retBigPlateCnt = 7 ; retMidPlateCnt = 7 ; } }else if( mmc->_first && mmc->_second==nullptr ) { if( mmc->_first->_type.find("A") != string::npos ) { retBigPlateCnt = 6 ; retMidPlateCnt = 7 ; }else if( mmc->_first->_type.find("B") != string::npos ) { retBigPlateCnt = 9 ; retMidPlateCnt = 0 ; }else if( mmc->_first->_type.find("C") != string::npos ) { retBigPlateCnt = 10 ; retMidPlateCnt = 0 ; } }else { retBigPlateCnt = 9 ; retMidPlateCnt = 0 ; } }