diff --git a/build/codeblocks/timberAllocation.cbp b/build/codeblocks/timberAllocation.cbp
index f4ccd2d..91ff149 100644
--- a/build/codeblocks/timberAllocation.cbp
+++ b/build/codeblocks/timberAllocation.cbp
@@ -12,7 +12,7 @@
-
+
diff --git a/src/TimberAllocation.h b/src/TimberAllocation.h
index b9ca774..102bdd8 100644
--- a/src/TimberAllocation.h
+++ b/src/TimberAllocation.h
@@ -76,7 +76,7 @@ class cTimber : public cSpace
void used( bool f = true )
{
- myUsed = true;
+ myUsed = f;
}
bool isUsed() const
{
@@ -93,6 +93,15 @@ class cTimber : public cSpace
return myLevel;
}
+ void usedbyLevel( bool f )
+ {
+ myUsedbyLevel = f;
+ }
+ bool isUsedbyLevel()
+ {
+ return myUsedbyLevel;
+ }
+
std::string myUserID;
int myCount;
@@ -101,6 +110,7 @@ class cTimber : public cSpace
timber_t myStock; // if an allocated order, the stock allocated to
bool myUsed; // true if a stock that haveen used to cut orders
int myLevel; // the location of the top of the highest level cut
+ bool myUsedbyLevel; // true if stock has been allocated to current level
};
class cInventory
@@ -153,14 +163,18 @@ class cLevel
public:
timberv_t myOrder; // orders
timber_t myStock; // stock allocated to level
- int myAreaUsed;
cLevel()
: myAreaUsed( 0 )
{
}
- void removePacked(); // remove orders that have been packed
+
+ /** remove orders that have been packed
+ @return 0: none packed, 1: some packed, 2: all packed
+ */
+ int removePacked();
+
std::string text() const;
int height() const
{
@@ -174,10 +188,16 @@ class cLevel
{
myAreaUsed += order->myLength * order->myWidth;
}
- int wastage() const
- {
- return height() * ( myStock->myLength * myStock->myWidth - myAreaUsed );
- }
+ /** Volume wasted when level cut from stock
+ @return volume wasted
+
+ This calculates wastage only for the currently stacked level
+ so this needs to be called for each stacked level
+ */
+ int wastage() const;
+
+private:
+ int myAreaUsed;
};
class cInstance
@@ -203,6 +223,14 @@ class cInstance
*/
void expandCount();
+ /// Number of orders that could not fit
+ int unPackedCount() const
+ {
+ return (int)myUnpacked.size();
+ }
+
+ bool isEveryIDUnique();
+
timberv_t myOrder; /// the timbers that have to be delivered
std::vector> myAllocation;
@@ -280,7 +308,7 @@ bool CS2LNW(
cLevel& level, int h );
/// Use pack2 engine to do 2D level cutting
-bool CS2Pack2(
+void CS2Pack2(
cInstance& I,
cLevel& level, int h );
@@ -300,11 +328,13 @@ void AllocateOrder(
/** Record the V cut for a level in the instance
@param[in] I the instance
- @param[in] level
+ @param[in] stock
+ @param[in] h height for cut at top of level
*/
void CutLevel(
cInstance& I,
- cLevel& level );
+ timber_t stock,
+ int h );
void ReturnToInventory(
cInventory& I );
diff --git a/src/taCutter.cpp b/src/taCutter.cpp
index 21b1a6c..c216008 100644
--- a/src/taCutter.cpp
+++ b/src/taCutter.cpp
@@ -65,6 +65,8 @@ void LevelsToStock(
std::vector< cLevel >& levels,
cInventory& inventory )
{
+ for( timber_t t : inventory.myStock )
+ t->usedbyLevel( false );
for ( auto& level : levels )
{
LevelToStock( I, level, inventory.myStock );
@@ -87,7 +89,11 @@ LevelToStock(
bool found = false;
for( timber_t t : stock )
{
- if( t->isUsed() )
+ // check if this stock was previously allocated to this level
+ // if so, it means that the level could not be packed into the stock
+ // probably because the W and/or length were too short
+ // in any case we do not want to allocate the stock again
+ if( t->isUsedbyLevel() )
continue;
int stockHeight = t->myHeight;
@@ -132,11 +138,15 @@ void LevelCuts(
cInventory& inventory )
{
bool allPacked;
+
// loop over levels
for( cLevel& level : levels )
{
std::cout << "cutting level " << level.text() << "\n";
+ for( timber_t t : inventory.myStock )
+ t->usedbyLevel( false );
+
do
{
/* stack levels
@@ -151,16 +161,20 @@ void LevelCuts(
h < level.myStock->myHeight; // does stock have enough height to stack another level?
h += level.height() ) // up one level
{
+
// Use 2D cutting algorithm to cut orders from level.
#ifdef USE_CS2LNW
allPacked = CS2LNW( I, level, h );
#endif // USE_CS2LNW
#ifdef USE_CS2Pack2
- allPacked = CS2Pack2( I, level, h );
+ CS2Pack2( I, level, h );
#endif // CS2Pack2
- if( allPacked )
+ // remove packed timbers from level
+ int ret = level.removePacked();
+
+ if( ret == 2 )
{
// all timbers in this level are packed
std::cout << "all timbers in this level are packed\n";
@@ -168,24 +182,33 @@ void LevelCuts(
break;
}
- // remove timbers from level that have been packed
- level.removePacked();
-
- // TODO: return unused remainders to inventory
+ if( ret == 1 )
+ {
+ // some packed
+ continue;
+ }
- if( ! allPacked )
+ if( ret == 0 )
{
- // stock timber exhausted, need to allocate another
- if( ! LevelToStock( I, level, inventory.myStock ) )
- {
- // no suitable stock available
- std::cout << " no suitable stock available\n";
- I.addUnpacked( level.myOrder );
- allPacked = true;
- }
+ // nothing packed
+ level.myStock->usedbyLevel( true );
+ break;
}
+ } // loop back to cut another level from the stock
+
+ if( ! allPacked )
+ {
+ // stock timber exhausted, need to allocate another
+ if( ! LevelToStock( I, level, inventory.myStock ) )
+ {
+ // no suitable stock available
+ std::cout << " no suitable stock available\n";
+ I.addUnpacked( level.myOrder );
+ return;
+ }
}
+
}
while( ! allPacked );
}
@@ -194,8 +217,6 @@ void LevelCuts(
// success
return;
}
-
-
}
bool CS2LNW(
cInstance& I,
@@ -245,7 +266,7 @@ bool CS2LNW(
return allPacked;
}
-bool CS2Pack2(
+void CS2Pack2(
cInstance& I,
cLevel& level, int h )
{
@@ -295,7 +316,8 @@ bool CS2Pack2(
*/
CutLevel(
I,
- level );
+ level.myStock,
+ h + level.height() );
}
AllocateOrder(
@@ -309,7 +331,7 @@ bool CS2Pack2(
if( ! packedCount )
{
std::cout << "nothing fit\n";
- return false;
+ return;
}
// at least one order was cut for this stock
@@ -352,8 +374,6 @@ bool CS2Pack2(
// add it to the instance cut list
I.myCut.push_back( cut );
}
-
- return ( packedCount == level.size() );
}
void AllocateOrder(
@@ -376,13 +396,13 @@ void AllocateOrder(
}
void CutLevel(
cInstance& I,
- cLevel& level )
+ timber_t stock,
+ int h )
{
- timber_t stock = level.myStock;
- stock->level( level.height() );
+ stock->level( h );
- if( level.height() == stock->myHeight )
+ if( h == stock->myHeight )
{
//no need for a cut, we are at the top of the stock
return;
@@ -390,8 +410,8 @@ void CutLevel(
I.myCut.push_back( cCut(
stock,
'H',
- level.height(),
- level.height() ));
+ h,
+ h ));
}
void ReturnToInventory(
@@ -404,21 +424,12 @@ void ReturnToInventory(
I.myStock.end(),
[] ( timber_t t )
{
- std::cout << "remove? " <isUsed() <<" " <level() <<" "<myHeight << "\n";
- return( t->isUsed() && t->level() == t->myHeight );
+ t->level( 0 );
+ t->used( false );
+ return( ! t->myHeight );
} ),
I.myStock.end() );
- // adjust height of partially used stock
- for( timber_t t : I.myStock )
- {
- if( ! t->isUsed() )
- continue;
-
- t->myHeight -= t->level();
- t->level( 0 );
- t->used( false );
- }
}
void DisplayWastage( std::vector& levels )
{
diff --git a/src/taInstance.cpp b/src/taInstance.cpp
index 7c70903..5172569 100644
--- a/src/taInstance.cpp
+++ b/src/taInstance.cpp
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
#include
#include "TimberAllocation.h"
@@ -38,6 +39,7 @@ void cInstance::read(
break;
}
}
+ isEveryIDUnique();
Inventory.expandCount();
expandCount();
}
@@ -95,5 +97,38 @@ void cInstance::addUnpacked( timberv_t& unpacked )
myUnpacked.end(),
unpacked.begin(), unpacked.end() );
}
+bool cInstance::isEveryIDUnique()
+{
+ std::set IDset, dupIDset;
+ bool first = true;
+ for( timber_t t: myOrder )
+ {
+ if( ! IDset.insert( t->myUserID ).second )
+ {
+ if( dupIDset.insert( t->myUserID ).second )
+ {
+ if( first )
+ {
+ std::cout << "Discarding duplicate IDs ( tid11 ):\n";
+ first = false;
+ }
+ std::cout << t->myUserID << " ";
+ }
+ }
+ }
+
+ myOrder.erase(
+ remove_if(
+ myOrder.begin(),
+ myOrder.end(),
+ [&dupIDset] ( timber_t t )
+ {
+ return( dupIDset.find(t->myUserID) != dupIDset.end() );
+ } ),
+ myOrder.end() );
+
+ std::cout << "\n" << myOrder.size() << " unique order IDs\n";
+ return true;
+}
}
diff --git a/src/taLevel.cpp b/src/taLevel.cpp
index 2f8c2a3..0f84925 100644
--- a/src/taLevel.cpp
+++ b/src/taLevel.cpp
@@ -8,8 +8,12 @@
namespace ta
{
-void cLevel::removePacked()
+int cLevel::removePacked()
{
+ int start = size();
+ if( ! start )
+ throw std::runtime_error( "removePacked");
+
myOrder.erase(
remove_if(
myOrder.begin(),
@@ -19,7 +23,27 @@ void cLevel::removePacked()
return( t->isPacked() );
} ),
myOrder.end() );
+
+ int stop = size();
+ int ret;
+ if( stop == start )
+ ret = 0;
+ else if( stop )
+ ret = 1;
+ else
+ ret = 2;
+
+ if( ret )
+ myStock->myHeight -= height();
+
+ return ret;
}
+int cLevel::wastage() const
+ {
+ if( ! size() )
+ return 0;
+ return height() * ( myStock->myLength * myStock->myWidth - myAreaUsed );
+ }
std::string cLevel::text() const
{
std::stringstream ss;
diff --git a/src/taTimber.cpp b/src/taTimber.cpp
index fa220bb..523c622 100644
--- a/src/taTimber.cpp
+++ b/src/taTimber.cpp
@@ -49,6 +49,7 @@ void cTimber::pack( int l, int w, int h, timber_t stock )
myLocW = w;
myLocH = h;
myStock = stock;
+ stock->used();
}