//
//  DecorationMatcher.m
//  ArmorP3V1
//
//  Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
//

#import "DecorationMatcher.h"
#import "Repository.h"
#import "DoubleArray.h"
#import "IntArray.h"
#import "DecorationSlot.h"
#import "PSWrap.h"
#import "PSItemType.h"
#import "PSMutex.h"

@implementation DecorationMatcher

@synthesize decorations = _decorations;
@synthesize quickScan = _quickScan;
@synthesize existConflict = _existConflict;
@synthesize conflictMatcher = _conflictMatcher;
@synthesize targetSkills = _targetSkills;
@synthesize useAnotherCheck = _useAnotherCheck;
@synthesize existAnotherSlot = _existAnotherSlot;
@synthesize existAnotherSkill = _existAnotherSkill;
@synthesize decorationWeight = _decorationWeight;
@synthesize existSomeRelation = _existSomeRelation;
@synthesize pool1 = _pool1;
@synthesize relationCache = _relationCache;
@synthesize step_cache = _step_cache;
@synthesize poolQueue = _poolQueue;
@synthesize poolAlready1 = _poolAlready1;
@synthesize poolAlready2 = _poolAlready2;
@synthesize firstSlot = _firstSlot;
@synthesize searchHunterType = _searchHunterType;
@synthesize searchHunterRank = _searchHunterRank;
@synthesize searchTownRank = _searchTownRank;
@synthesize searchGenderType = _searchGenderType;
@synthesize cache1 = _cache1;

-(void)dealloc {
    [_conflictMatcher release];
    [_decorationWeight release];
    [_pool1 release]; 
    [_relationCache release];
    [_targetSkills release];
    [_decorations release];
    [_step_cache release];
    [_cache1 release];
    [_poolQueue release];
    [_poolAlready1 release];
    [_poolAlready2 release];
    [_firstSlot release];
    [super dealloc];
}


-(void)decoQueStandby:(NSMutableArray*)skillList:(int)availSlotCount {
    
}


-(id)initWithData: (PSSession*)session {
    self = [super init];
    if (self) {
        _quickScan = true;
        _useAnotherCheck = false;
        _existAnotherSkill = false;
        _existAnotherSlot = false;
        _conflictMatcher = nil;
        _decorationWeight = [[NSMutableDictionary alloc]init];
        _pool1 = [[RelationKey alloc]init];
        _relationCache = [[NSMutableDictionary alloc]init];
        _cache1 = [[SkillSet alloc]init];
        _poolQueue = nil;
        _poolAlready1 = nil;
        _poolAlready2 = nil;
        _firstSlot = nil;
        
        if (_decorationWeight == nil || _pool1 == nil || _relationCache == nil || _cache1 == nil) {
            [[PSMutex mainMutex] raiseMemoryError];
            [[PSMutex mainMutex] showMemoryAlertIfError];
            return nil;
        }
        
        [_targetSkills release];
        _targetSkills = [[SkillSet alloc]init];
        [_targetSkills set_all:session.searchSkills];
        [_decorations release];
        _decorations = [[NSMutableArray alloc]init];
        
        if (_targetSkills == nil || _decorations == nil) {
            [[PSMutex mainMutex] raiseMemoryError];
            [[PSMutex mainMutex] showMemoryAlertIfError];
            return nil;
        }
        
        _searchHunterType = session.searchHunterType;
        _searchGenderType = session.searchGenderType;
        _searchHunterRank = session.searchHunterRank;
        _searchTownRank = session.searchTownRank;
        
        Repository* repository = [Repository mainRepository];
        NSMutableArray* deco0 = repository.items.listDecoration;
        
        NSMutableDictionary** already = calloc(sizeof(NSMutableDictionary*), 4);
        for (int i = 0; i <= 3; ++ i) {
            already[i] = [[NSMutableDictionary alloc]init];
        }
        
        for(int i = 0; i < deco0.count; ++ i) {
            PSItem* deco = [deco0 objectAtIndex: i];
            
            if ([self decoIsForSkillKind:deco: _targetSkills]) {
                if (deco.existHunterRank > _searchHunterRank
                    && deco.existTownRank > _searchTownRank) {
                    continue;
                }
                
                SkillSet* masked = [[SkillSet alloc]initWithColumn:_targetSkills];
                [masked set_only: deco.skills];
                
                NSMutableDictionary* dict = already[deco.slotCount];
                
                PSWrap* wrap = [[PSWrap alloc]initWithItem:deco :masked];
                if (wrap == nil) {                    
                    [[PSMutex mainMutex] raiseMemoryError];
                    [[PSMutex mainMutex] showMemoryAlertIfError];
                    return nil;
                }
                [wrap.maskedSkills sum_fixed: masked];
                NSMutableArray* listDeco = [dict objectForKey:masked];
                if (listDeco == nil) {
                    NSMutableArray* array = [[NSMutableArray alloc]init];
                    [dict setObject:array forKey:masked];
                    [array release];
                    listDeco = array;
                }
                [listDeco addObject: wrap];
            }
        }        
        
        for (int x = 0; x <= 3; ++ x) {
            NSMutableDictionary* dict = already[x];
            NSEnumerator* en = nil;
            while (dict.count > 0) {
                if (en == nil) {
                    en = [dict keyEnumerator];
                }
                SkillSet* skills = [en nextObject];
                if (skills == nil) {
                    break;
                }
                NSMutableArray* array = [dict objectForKey: skills];
                if (array.count < 2) {
                    for (int i = 0; i < array.count; ++ i) {
                        PSWrap* wrap = [array objectAtIndex:i];
                        [_decorations addObject:wrap];
                    }
                }else {
                    int v = -1;
                    for (int i = 0; i < skills.count; ++ i) {
                        if (skills.point[i] != 0) {
                            v = i;
                            break;
                        }
                    }
                    if (v < 0) {
                        NSException *exception = [[NSException alloc]initWithName:@"memoryerror" reason:@"nil" userInfo:nil];
                        [exception raise];
                    }
                    SkillKind* kind = [skills.listKind objectAtIndex:v];
                    NSString* title = [NSString stringWithFormat:@"珠{%@=%d}", kind.name, skills.point[v]];
                    PSItem* item = [[PSItem alloc]init];
                    item.name = title;
                    item.slotCount = x;
                    item.skills = [[SkillSet alloc]init];
                    [item.skills sum_all:skills];
                    [item.skills release];
                    
                    PSWrap* wrap = [[PSWrap alloc]initWithItem:item :nil];
                    [item release];
                    [wrap.maskedSkills set_all:skills];
                    
                    [_decorations addObject:wrap];
                    
                    /*
                     if (wrap.sameArmors == nil) {
                     wrap.sameArmors = [[NSMutableArray alloc]init];
                     }*/
                    [wrap.sameArmors addObjectsFromArray:array];
                    
                    [wrap release];
                }
            }
        }
        
        IntArray* fullRelation = [self getPlusRelationCached: _targetSkills];
        _existSomeRelation = fullRelation != nil ? TRUE : FALSE;
        if (_existSomeRelation) {
            int x = fullRelation.count;
            for (int i = 0; i < x; ++i) {
                if (fullRelation.array[i] != 0) {
                    _existConflict = true;
                }
            }
        }
        if (_existConflict) {
            /*
            SkillSet* skill1 = _targetSkills;
            SkillSet* skill2 = [[SkillSet alloc]init];
            [skill2 set_all:skill1];
            for (int x = 0; x < skill1.count; ++x) {
                SkillKind* kind = [skill1.listKind objectAtIndex:x];
                int point = skill1.point[x];
                BOOL positive = skill1.positive[x];
                if (positive) {
                    [skill2 set:kind :point :positive];
                } else {
                    [skill2 set:kind :0 :FALSE];
                }
            }
            
            PSSession* session2 = [session makeCopy];
            session2.searchSkills = skill2;
            _conflictMatcher = [[DecorationMatcher alloc]initWithData:session2];
            [skill2 release];
            [session2 release];
             */
        }
        for (int i = 0; i <= 3; ++ i) {
            [already[i] release];
        }
    }else {
        [[PSMutex mainMutex] raiseMemoryError];
    }
    [[PSMutex mainMutex] showMemoryAlertIfError];
    return self;
}

-(double)getDecorationWeight:(SkillKind*)kind :(BOOL) range:(int)slotMax {
    DoubleArray* x = [_decorationWeight objectForKey: kind];
    if (x == nil) {
        x = [[DoubleArray alloc]init];
        if (x == nil) {
            [[PSMutex mainMutex] raiseMemoryError];
            [[PSMutex mainMutex] showMemoryAlertIfError];
            return 0;
        }
        [x ensureCapacity: 5];
        for (int width = 0; width <= 3; width++) {
            double savedWeight = 10;
            for (int i = 0; i < _decorations.count; ++i) {
                PSWrap* deco = [_decorations objectAtIndex:i];
                SkillSet* skills = deco.item.skills;
                int n = [skills findByKind:kind];
                if (n < 0) {
                    continue;
                }
                if (deco.item.slotCount > width) {
                    continue;
                }
                int point = skills.point[n];
                if (!range) {
                    point = -point;
                }
                if (point >= 1) {
                    double weight = (double) point;
                    weight = deco.item.slotCount / weight;
                    
                    if (weight < savedWeight) {
                        savedWeight = weight;
                    }
                }
            }
            x.array[width] = savedWeight;
        }
        [_decorationWeight setObject:x forKey:kind];
        [x release];
    }
    return x.array[slotMax];
}

static IntArray* save_intarray = nil;

-(IntArray*)getPlusRelationCached: (SkillSet*)diffSkills {
    [_pool1 set:diffSkills];
    
    IntArray* ret = [_relationCache objectForKey:_pool1];
    
    if (ret != nil) {
        if (ret.count == 0) {
            return nil;
        }
        return ret;
    }
    
    ret = [self getPlusRelation: diffSkills];
    
    if (ret == nil) {
        if (save_intarray == nil) {
            save_intarray = [[IntArray alloc]init];
        }
        ret = save_intarray;
        [ret retain];
    }
    
    RelationKey* pool2 = [_pool1 makeCopy];
    [_relationCache setObject:ret forKey: pool2];
    [pool2 release];
    [ret release];
    
    if (ret == save_intarray || ret.count == 0) {
        return nil;
    }
    return ret;
}

-(IntArray*)getPlusRelation:(SkillSet*)diffSkills {
    IntArray* relation = [[IntArray alloc]init];
    [relation ensureCapacity:diffSkills.count];
    BOOL found = false;
    int counter = 1;
    for (int i = 0; i < relation.count; ++i) {
        relation.array[i] = 0;
    }
    for (int i = 0; i < diffSkills.count; ++i) {
        SkillKind* kind = [diffSkills.listKind objectAtIndex:i];
        BOOL range = diffSkills.positive[i];
        int point = diffSkills.point[i];
        if (range && point <= 0) {
            continue;
        }
        if (!range && point >= 0) {
            continue;
        }
        for (int k = 0; k < _decorations.count; ++k) {
            PSWrap* deco = [_decorations objectAtIndex:k];
            int x = [deco.item.skills findByKind:kind];
            if (x < 0) {
                continue;
            }
            int decoPoint = deco.item.skills.point[x];
            if (range && decoPoint <= 0) {
                continue;
            }
            if (!range && decoPoint >= 0) {
                continue;
            }
            //now, found decoration
            //check another plus
            for (int q = 0; q < deco.item.skills.count; ++ q) {
                if (q == x) {
                    continue;
                }
                SkillKind* anotherDecoSkill = [deco.item.skills.listKind objectAtIndex: (q)];
                int anotherDecoPoint = deco.item.skills.point[q];
                
                for (int j = 0; j < diffSkills.count; ++j) {
                    if (i == j) {
                        continue;
                    }
                    SkillKind* kind2 = [diffSkills.listKind objectAtIndex:j];
                    if (kind2 != anotherDecoSkill) {
                        continue;
                    }
                    BOOL range2 = diffSkills.positive[j];
                    int point2 = diffSkills.point[j];
                    if (range2 && point2 <= 0) {
                        continue;
                    }
                    if (!range2 && point2 >= 0) {
                        continue;
                    }
                    if (range2 && anotherDecoPoint <= 0) {
                        continue;
                    }
                    if (!range2 && anotherDecoPoint >= 0) {
                        continue;
                    }
                    //now, found another plus
                    found = true;
                    if (relation.array[i] >= 1) {
                        if (relation.array[i] == relation.array[j]) {
                            continue;
                        } else if (relation.array[j] >= 1) {
                            int org = relation.array[j];
                            for (int m = 0; m < relation.count; ++m) {
                                if (relation.array[m] == org) {
                                    relation.array[m] = relation.array[i];
                                }
                            }
                        } else {
                            relation.array[j] = relation.array[i];
                        }
                    } else if (relation.array[j] >= 1) {
                        if (relation.array[i] == relation.array[j]) {
                            continue;
                        } else if (relation.array[i] >= 1) {
                            int org = relation.array[i];
                            for (int m = 0; m < relation.count; ++m) {
                                if (relation.array[m] == org) {
                                    relation.array[m] = relation.array[j];
                                }
                            }
                        } else {
                            relation.array[i] = relation.array[j];
                        }
                    } else {
                        relation.array[i] = counter;
                        relation.array[j] = counter;
                        counter++;
                    }
                }
            }
        }
    }
    if (found) {
        return relation;
    }
    return nil;
}

-(int)getNeedSlotCount:(DecorationSlot*)slot {
    int width = [slot getSlotMaxCount];
    int width2 = [slot getBodyAvailable];
    
    if (width2 > width) {
        width = width2;
    }
    
    if (_step_cache == nil || _step_cache.count != slot.diffSkills.count) {
        [_step_cache release];
        _step_cache = [[IntArray alloc]init];
        [_step_cache ensureCapacity:slot.diffSkills.count];
    }
    int* stepCount = _step_cache.array;
    for (int i = 0; i < _step_cache.count; ++i) {
        stepCount[i] = 0;
    }
    
    int needSlotCount = 0;
    for (int i = 0; i < slot.diffSkills.count; ++i) {
        SkillKind* kind = [slot.diffSkills.listKind objectAtIndex:i];
        BOOL range = slot.diffSkills.positive[i];
        int point = slot.diffSkills.point[i];
        if (!range) {
            point = -point;
        }
        if (point >= 1) {
            double weight = [self getDecorationWeight:kind :range :width];
            stepCount[i] = (int) ceil(weight * point - 0.1);
        }
    }
    
    needSlotCount = 0;
    for (int i = 0; i < slot.diffSkills.count; ++i) {
        needSlotCount += stepCount[i];
    }
    
    if (needSlotCount == 0) {
        return 0;
    }
    //another have minus
    //-> nothing
    
    //another have plus
    //-> only_max(that, another)
    if (_existSomeRelation) {
        IntArray *relation = [self getPlusRelationCached: slot.diffSkills];
        if (relation != nil && relation.count > 0) {
            int* sumPositive = calloc(sizeof(int), slot.diffSkills.count);
            int* sumNegative = calloc(sizeof(int), slot.diffSkills.count);
            if (sumPositive == nil || sumNegative == nil) {
                [[PSMutex mainMutex] raiseMemoryError];
                [[PSMutex mainMutex] showMemoryAlertIfError];
                return 10000;
            }
            for (int x = 0; x < relation.count; ++x) {
                int pos = relation.array[x];
                
                if (pos == 0 || slot.diffSkills.positive[x]) {
                    sumPositive[pos] += stepCount[x];
                } else {
                    sumNegative[pos] += stepCount[x];
                }
            }
            needSlotCount = 0;
            for (int i = 0; i < slot.diffSkills.count; ++i) {
                if (i == 0) {
                    needSlotCount += sumPositive[i] + sumNegative[i];
                } else if (sumPositive[i] > sumNegative[i]) {
                    needSlotCount += sumPositive[i];
                } else {
                    needSlotCount += sumNegative[i];
                }
            }
            free(sumPositive);
            free(sumNegative);
            return needSlotCount;
        } else {
            return needSlotCount;
        }
    } else {
        return needSlotCount;
    }
}

-(BOOL)canHaveEnoughDecoration:(PSArmorSet*)armorSet :(BOOL)fullScan :(NSMutableArray*)result {
    if (_useAnotherCheck) {
        _existAnotherSlot = FALSE;
        _existAnotherSkill = FALSE;
    }
    
    if (_conflictMatcher != nil) {
        if ([_conflictMatcher canHaveEnoughDecoration:armorSet :fullScan :nil] != TRUE) {
            return FALSE;
        }
    }
    
    NSMutableArray* queue = _poolQueue;
    if (queue == nil) {
        queue = [[NSMutableArray alloc]init];
        if (queue == nil) {                    
            [[PSMutex mainMutex] raiseMemoryError];
            [[PSMutex mainMutex] showMemoryAlertIfError];
            return FALSE;
        }
        _poolQueue = queue;
    }
    [queue removeAllObjects];
    
    NSMutableSet* already = _poolAlready1;
    if (already == nil) {
        _poolAlready1 = [[NSMutableSet alloc]init];
        already = _poolAlready1;
        if (already == nil) {  
            [[PSMutex mainMutex] raiseMemoryError];
            [[PSMutex mainMutex] showMemoryAlertIfError];
            return FALSE;
        }
    }
    [already removeAllObjects];
    
    BOOL found = false;
    
    armorSet.targetSkills = self.targetSkills;
    [armorSet calculateUseList:self.targetSkills];
    SkillSet* diffSkill = _cache1;
    [diffSkill set_all:_targetSkills];
    [diffSkill minus_only:armorSet.setSkills];
    
    if (_firstSlot == nil) {
        _firstSlot = [[DecorationSlot alloc]init];
        if (_firstSlot == nil) {                  
            [[PSMutex mainMutex] raiseMemoryError];
            [[PSMutex mainMutex] showMemoryAlertIfError];
            return FALSE;
        }
    }
    DecorationSlot* slot = _firstSlot;
    [_firstSlot retain];
    
    [slot beginWithDecorationAndArmorSet:_decorations :armorSet];
    
    int slotCount = armorSet.weaponSlotCount;
    if (slotCount < 0) {
        slotCount = 0;
    }
    
    [slot construct:diffSkill :armorSet :slotCount];
    
    [queue addObject:slot];
    [slot release];
    
    int lp = 0;
    
    while(queue.count != 0) {
        [[PSMutex mainMutex] showMemoryAlertIfError];
        slot = [queue lastObject];
        [slot retain];
        [queue removeLastObject];
        lp ++;
        
        int needSlotCount = [self getNeedSlotCount: slot];
        int totalAvailCount = [slot totalAvailCount];
        
        if ([already containsObject:slot]) {
            continue;
        }

        [already addObject:slot];

        if (needSlotCount > 0 && needSlotCount > totalAvailCount) {
            continue;
        }

        /*if (debug) {
            NSLog(@"%@", armorSet.setSkills);
            NSLog(@"need = %d avail = %d %@", needSlotCount, totalAvailCount, armorSet);
        }*/

        if (armorSet.weaponSlotCount < 0) {
            if (needSlotCount == 0) {
                if (result != nil) {
                    [result addObject:slot];
                }
                found = TRUE;
                return TRUE;
            } else {
                return FALSE;
            }
        }
        
        BOOL hit = /*[slot.diffSkills totalDiffPoint]*/needSlotCount == 0 ? TRUE : FALSE;
        
        /*
         if (hit && searchWithUsableStatus && _items != nil) {
         if ([self checkUsableCount: slot] == FALSE) {
         hit = FALSE;
         }
         }*/
        
        if (hit) {
            found = TRUE;
            if (result != nil) {
                [result addObject: slot];
            }else {
            }
            [slot release];
            if (!fullScan) {
                return found;
            }
            continue;
        }
        int bodyWidth = [slot getBodyAvailable];
        int maxWidth = [slot getSlotMaxCount];
        
        for (int i = 0; i < _decorations.count; ++i) {
            PSWrap* deco = [_decorations objectAtIndex: i];
            if (_existConflict || [self decoIsForDiffSkill: deco.item: slot.diffSkills: _quickScan ]) {
                if (bodyWidth >= deco.item.slotCount) {
                    DecorationSlot* next = [slot applyToBody: deco];
                    if (next != nil) {
                        [queue addObject:next];
                    }
                    [next release];
                }
                if (maxWidth >= deco.item.slotCount) {
                    DecorationSlot* next2 = [slot applyAuto: deco];
                    if (next2 != nil) {
                        [queue addObject:next2];
                    }
                    [next2 release];
                }
            }
        }
        
        [slot release];
    }
    
    if (fullScan) {
        NSEnumerator* en = [result objectEnumerator];
        NSMutableArray* listRemove = [[NSMutableArray alloc]init];
        
        while(TRUE) {
            slot = en.nextObject;
            if (slot == nil) {
                break;
            }
            if ([slot canRemoveFromBody] || [slot canRemoveFromNotBody]) {
                [listRemove addObject:slot];
            }
        }
        for (int i = 0; i < listRemove.count; ++ i) {
            slot = [listRemove objectAtIndex:i];
            [result removeObject: slot];
        }
        [listRemove release];
    }
    return found;
}

-(BOOL)checkUsableCount:(DecorationSlot*)set {
    return TRUE;
    /*
     if (_items.searchUsableCount == nil) {
     return true;
     }
     
     DecorationCount* map = [[DecorationCount alloc]init];
     [map resetWithColumn:_decorations];
     [map addAll: set.mapBodyDecoration];
     [map addAll: set.mapDecoration];
     
     for (int i = 0; i < map.count; ++ i) {
     PSItem* item = [map.listDeco objectAtIndex:i];
     int count = map.listCount[i];
     
     NSNumber* x = [_items.searchUsableCount objectForKey:item];
     if (x != nil) {
     if (count > x.intValue) {
     [map release];
     return false;
     }
     }
     }
     [map release];
     return true;
     */
}

-(BOOL)decoIsForDiffSkill: (PSItem*) item: (SkillSet*) skills:(BOOL) quickScan {
    for (int i = 0; i < skills.count; ++i) {
        SkillKind* kind = [skills.listKind objectAtIndex:i];
        BOOL range = skills.positive[i];
        int point1 = skills.point[i];
        
        if ((range && point1 >= 1) || (!range && point1 <= -1)) {
            int x = [item.skills findByKind:kind];
            if (x >= 0) {
                int point2 = item.skills.point[x];
                if (range) {
                    if (point2 >= 1) {
                        return TRUE;
                    }
                } else {
                    if (point2 <= -1) {
                        return TRUE;
                    }
                }
            }
        }
    }
    return FALSE;
}

-(BOOL)decoIsForSkillKind:(PSItem*) item: (SkillSet*) skills {
    for (int i = 0; i < skills.count; ++i) {
        SkillKind* kind = [skills.listKind objectAtIndex:i];
        BOOL range = skills.positive[i];
        //int point1 = skills.point[i];
        
        int x = [item.skills findByKind:kind];
        if (x >= 0) {
            int point2 = item.skills.point[x];
            if (range) {
                if (point2 >= 1) {
                    return TRUE;
                }
            } else {
                if (point2 <= -1) {
                    return TRUE;
                }
            }
        }
    }
    return FALSE;
}

+(BOOL)existMoreSlot:(NSMutableArray*) prevResult {
    for(int i = 0; i < prevResult.count; ++ i) {
        DecorationSlot* slot = [prevResult objectAtIndex:i];
        int x = slot.totalAvailCount;
        if (x >= 1) {
            return TRUE;
        }
    }
    return FALSE;
}

-(int)fixRealWeaponSlot:(PSArmorSet*) set: (NSArray*) prevResult {
    if (set.weaponSlotCount <= 0) {
        return set.weaponSlotCount;
    }
    
    int maxAvailable = 0;
    for (int i = 0; i < prevResult.count; ++ i) {
        DecorationSlot* slot = [prevResult objectAtIndex:i];
        int x = [slot getWeaponSlotAvailable];
        if (x >= maxAvailable) {
            maxAvailable = x;
        }
    }
    return set.weaponSlotCount - maxAvailable;
}

-(BOOL)isCharmHaveReplacement: (PSArmorSet*) set: (PSWrap*) noneItem {
    PSWrap* charm = [set.listArmor objectAtIndex: ITEM_TYPE_CHARM];
    if (charm == nil) {
        return false;
    }
    
    BOOL found = FALSE;
    if (charm != noneItem) {
        [set.listArmor replaceObjectAtIndex:ITEM_TYPE_CHARM withObject:noneItem];
        //[set calculateUseList:_targetSkills];
        if ([self canHaveEnoughDecoration:set :false :nil]) {
            found = true;
        }
    }
    
    if (!found) {
        for (int i = 0; i < charm.childArmors.count; ++ i) {
            PSWrap* replace = [charm.childArmors objectAtIndex:i];
            if (replace.item == charm.item) {
                continue;
            }
            [set.listArmor replaceObjectAtIndex:ITEM_TYPE_CHARM withObject:replace];
            
            //[set calculateUseList:_targetSkills];
            if ([self canHaveEnoughDecoration:set :false :nil]) {
                found = true;
                break;
            }
        }
    }
    
    [set.listArmor replaceObjectAtIndex:ITEM_TYPE_CHARM withObject:charm];
    [set calculateUseList:_targetSkills];
    return found;
}

@end
