<commit_before>package com.cibuddy.ibuddy;

import com.codeminders.hidapi.HIDDevice;
import com.codeminders.hidapi.HIDDeviceInfo;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Timer;
import java.util.TimerTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author mirkojahn
 */
public class IBuddyDefault extends TimerTask implements IBuddyFigure {

    private static final Logger LOG = LoggerFactory.getLogger(IBuddyDefault.class);
    public static final short DEVICE_PRODUCT = 0x0002;
    private static final long UPDATE_INTERVAL = 500L; // in ms
    private final HIDDeviceInfo deviceInfo;
    private HIDDevice device;
    
    // default values for the hardware state(s)
    private Color currentColor = Color.BLACK;
    private boolean heart = false;
    private Wings wings = Wings.NEUTRAL;
    private Turn direction = Turn.NEUTRAL;
    
    // complex state manipulation
    private final HeartBeat beatingHeard = new HeartBeat();
    private final WingFlapping wingsFlapping = new WingFlapping();
    private final Dancing dancing = new Dancing();
    
    // the current thread state(s)
    private final Object guard = new Object();
    private volatile boolean update = false;
    private volatile boolean enabled = false;
    
    private final Timer timer = new Timer();
    private final long EXECUTION_DELAY = 1000; // 1 Seconds
    
    public IBuddyDefault(HIDDeviceInfo devInfo) {
        deviceInfo = devInfo;
        
    }

    @Override
    public void open() throws IOException {
        synchronized (guard) {
            device = deviceInfo.open();
            enabled = true;
            timer.schedule(this, EXECUTION_DELAY, UPDATE_INTERVAL);
        }
    }

    @Override
    public void close() throws IOException {
        update = true;
        enabled = false; // see Thread.stop()
        updateState();
        timer.cancel();
        try {
            synchronized (guard) {
                if (device != null) {
                    device.close();
                    device = null;
                }
            }
        } catch (Exception ex) {
        }
    }

    @Override
    public void run() {
        try {
            // check if device is running (or there are pending actions)
            if (enabled | update) {

                // check complex types
                beatingHeard.check();
                wingsFlapping.check();
                dancing.check();
                if (update) {
                    // actually update the state
                    updateState();
                }

            }
        } catch (IOException ex) {
            LOG.warn("Problem writing state to the device. This most likely "
                    + "depends on the native code part or hardware.", ex);
        }
    }

    private int updateState() throws IOException {
        byte state = 0;
        state |= (byte) ((int) currentColor.getCode() << 4);
        state |= (byte) (heart ? 0 : 0x80);
        state |= (byte) ((int) wings.getCode() << 2);
        state |= (byte) (direction.getCode());
        return write(state);
    }

    @Override
    public void resetEverything() {
        setCurrentColor(Color.BLACK);
        setHeart(false);
        setWings(Wings.NEUTRAL);
        setDirection(Turn.NEUTRAL);
        beatingHeard.disable();
        wingsFlapping.disable();
        dancing.disable();
    }

    private int write(byte payload) throws IOException {
        int writtenBytes = 0;
        byte[] command = SET_COMMAND.clone();
        command[8] = payload;
        try {
            writtenBytes = device.sendFeatureReport(command);
            if(writtenBytes > 0){
                update = false;
            }
            LOG.debug("SUCCESS: command execution: " + new BigInteger(new byte[]{payload}).toString(16));
        } catch (Exception ex) {
            LOG.debug("FAILED: command execution: " + new BigInteger(new byte[]{payload}).toString(16));
        }
        return writtenBytes;
    }

    @Override
    public void setCurrentColor(Color currentColor) {
        if(!enabled){
            return;
        }
        this.currentColor = currentColor;
        update = true;
    }

    public void setDirection(Turn direction) {
        if(!enabled){
            return;
        }
        this.direction = direction;
        update = true;
    }

    @Override
    public void setHeart(boolean heart) {
        if(!enabled){
            return;
        }
        this.heart = heart;<commit_msg>Fixed i-Buddy usage (for Windows and OS X) - verified on 10.7.3, WinXP and Windows 8 Dev Preview<commit_after>package com.cibuddy.ibuddy;

import com.codeminders.hidapi.HIDDevice;
import com.codeminders.hidapi.HIDDeviceInfo;
import java.io.IOException;
import java.math.BigInteger;
import java.util.Timer;
import java.util.TimerTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author mirkojahn
 */
public class IBuddyDefault extends TimerTask implements IBuddyFigure {

    private static final Logger LOG = LoggerFactory.getLogger(IBuddyDefault.class);
    public static final short DEVICE_PRODUCT = 0x0002;
    private static final long UPDATE_INTERVAL = 500L; // in ms
    private final HIDDeviceInfo deviceInfo;
    private HIDDevice device;
    
    // default values for the hardware state(s)
    private Color currentColor = Color.BLACK;
    private boolean heart = false;
    private Wings wings = Wings.NEUTRAL;
    private Turn direction = Turn.NEUTRAL;
    
    // complex state manipulation
    private final HeartBeat beatingHeard = new HeartBeat();
    private final WingFlapping wingsFlapping = new WingFlapping();
    private final Dancing dancing = new Dancing();
    
    // the current thread state(s)
    private final Object guard = new Object();
    private volatile boolean update = false;
    private volatile boolean enabled = false;
    
    private final Timer timer = new Timer();
    private final long EXECUTION_DELAY = 1000; // 1 Seconds
    
    public IBuddyDefault(HIDDeviceInfo devInfo) {
        deviceInfo = devInfo;
        
    }

    @Override
    public void open() throws IOException {
        synchronized (guard) {
            device = deviceInfo.open();
            enabled = true;
            timer.schedule(this, EXECUTION_DELAY, UPDATE_INTERVAL);
        }
    }

    @Override
    public void close() throws IOException {
        update = true;
        enabled = false; // see Thread.stop()
        updateState();
        timer.cancel();
        try {
            synchronized (guard) {
                if (device != null) {
                    device.close();
                    device = null;
                }
            }
        } catch (Exception ex) {
        }
    }

    @Override
    public void run() {
        try {
            // check if device is running (or there are pending actions)
            if (enabled | update) {

                // check complex types
                beatingHeard.check();
                wingsFlapping.check();
                dancing.check();
                if (update) {
                    // actually update the state
                    updateState();
                }

            }
        } catch (IOException ex) {
            LOG.warn("Problem writing state to the device. This most likely "
                    + "depends on the native code part or hardware.", ex);
        }
    }

    private int updateState() throws IOException {
        byte state = 0;
        state |= (byte) ((int) currentColor.getCode() << 4);
        state |= (byte) (heart ? 0 : 0x80);
        state |= (byte) ((int) wings.getCode() << 2);
        state |= (byte) (direction.getCode());
        return write(state);
    }

    @Override
    public void resetEverything() {
        setCurrentColor(Color.BLACK);
        setHeart(false);
        setWings(Wings.NEUTRAL);
        setDirection(Turn.NEUTRAL);
        beatingHeard.disable();
        wingsFlapping.disable();
        dancing.disable();
    }

    private int write(byte payload) throws IOException {
        int writtenBytes = 0;
        byte[] command = SET_COMMAND.clone();
        command[8] = payload;
        try {
            // attempt 1:
//            device.disableBlocking();
//            device.writeTimeout(SETUP_COMMAND,100);
//            writtenBytes = device.writeTimeout(command, 100);
            
            
            // attempt 3:
            // working on windows and mac os (linux seems to have issues)
            device.write(SETUP_COMMAND);
            writtenBytes = device.write(command);
            
            
            // attempt 4:
//            device.sendFeatureReport(SETUP_COMMAND);
//            writtenBytes = device.sendFeatureReport(command);
//            
//            
            // attempt 5:
//            writtenBytes = device.writeTimeout(command, 100);
//            
//            
            // attempt 6:
//            writtenBytes = device.write(command);
//            
//            
            // attempt 7:
//            writtenBytes = device.sendFeatureReport(command);
            
            // adding blocking, then there are even more combinations to test
            
            if(writtenBytes > 0){
                update = false;
                LOG.debug("SUCCESS: command execution: {}", new BigInteger(new byte[]{payload}).toString(16));
            } else {
                LOG.debug("FAILED: command execution based on written bytes {} for command: {}", writtenBytes , new BigInteger(new byte[]{payload}).toString(16));
            }
        } catch (Exception ex) {
            LOG.debug("FAILED: command execution: {}", new BigInteger(new byte[]{payload}).toString(16));
        }
        return writtenBytes;
    }

    @Override
    public void setCurrentColor(Color currentColor) {
        if(!enabled){
            return;
        }
        this.currentColor = currentColor;
        update = true;
    }

    public void setDirection(Turn direction) {
        if(!enabled){
            return;
        }
        this.direction = direction;
        update = true;
    }

    @Override
    public void setHeart(boolean heart) {
        if(!enabled){
            return;
        }
        this.heart = heart;
{'fraction_non_alphanumeric': 0.09719390232061365, 'fraction_numerical': 0.0077677444412078845, 'mean_word_length': 1.828116419549698, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3315532', 'n_tokens_mistral': 2783, 'n_tokens_neox': 2648, 'n_words': 748}