<commit_before>/*
 Moses - factored phrase-based language decoder
 Copyright (C) 2010 University of Edinburgh

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License along
 with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

 */

#include <algorithm>
#include <cassert>
#include <cmath>
#include <fstream>
#include <sstream>
#include <stdexcept>
#include "StaticData.h"

#include "FeatureVector.h"

using namespace std;

namespace Moses {

  const string FName::SEP = "_";
  FName::Name2Id FName::name2id;
  vector<string> FName::id2name;

  void FName::init(const string& name)  {
    Name2Id::iterator i = name2id.find(name);
    if (i != name2id.end()) {
      m_id = i->second;
    } else {
      m_id = name2id.size();
      name2id[name] = m_id;
      id2name.push_back(name);
    }
  }

  std::ostream& operator<<( std::ostream& out, const FName& name) {
    out << name.name();
    return out;
  }

  size_t FName::hash() const {
    /*std::size_t seed = 0;
		 boost::hash_combine(seed, m_root);
		 boost::hash_combine(seed, m_name);
		 return seed;*/
    return boost::hash_value(m_id);
  }

  const std::string& FName::name() const {
    return id2name[m_id];
  }

  bool FName::operator==(const FName& rhs) const {
    return m_id == rhs.m_id;
  }

  bool FName::operator!=(const FName& rhs) const {
    return ! (*this == rhs);
  }

	FVector::FVector(FValue defaultValue)  {
    m_features[DEFAULT_NAME] = defaultValue;
	}

	void FVector::clear() {
    m_features.clear();
    m_features[DEFAULT_NAME] = DEFAULT;
	}

	void FVector::load(const std::string& filename) {
		ifstream in (filename.c_str());
		if (!in) {
			ostringstream msg;
			msg << "Unable to open " << filename;
			throw runtime_error(msg.str());
		}
		string line;
		while(getline(in,line)) {
			if (line[0] == '#') continue;
			istringstream linestream(line);
			string namestring;
			FValue value;
			linestream >> namestring;
			linestream >> value;
			FName fname(namestring);
			set(fname,value);
		}
  }

  void FVector::save(const string& filename) const {
    ofstream out(filename.c_str());
    if (!out) {
      ostringstream msg;
      msg << "Unable to open " << filename;
      throw runtime_error(msg.str());
    }
    write(out);
    out.close();
  }

  void FVector::write(ostream& out) const {
    for (const_iterator i = cbegin(); i != cend(); ++i) {
      out << i->first << " " << i->second << endl;
    }
  }

  FName FVector::DEFAULT_NAME("DEFAULT","");
  const FValue FVector::DEFAULT = 0;

  static bool equalsTolerance(FValue lhs, FValue rhs) {
    if (lhs == rhs) return true;
    static const FValue TOLERANCE = 1e-4;
    FValue diff = abs(lhs-rhs);
    FValue mean = (abs(lhs)+abs(rhs))/2;
    //cerr << "ET " << lhs << " " << rhs << " " << diff << " " << mean << " " << endl;
    return diff/mean < TOLERANCE ;
  }

  bool FVector::operator== (const FVector& rhs) const {
    if (this == &rhs) {
      return true;
    }
    if (get(DEFAULT_NAME) != rhs.get(DEFAULT_NAME)) return false;
    for (const_iterator i  = cbegin(); i != cend(); ++i) {
      if (!equalsTolerance(i->second,rhs.get(i->first))) return false;
    }
    for (const_iterator i = rhs.cbegin(); i != rhs.cend(); ++i) {
      if (!equalsTolerance(i->second, get(i->first))) return false;
    }
    return true;
  }

  bool FVector::operator!= (const FVector& rhs) const {
    return ! (*this == rhs);
  }

	ProxyFVector FVector::operator[](const FName& name) {
		// At this point, we don't know whether operator[] was called, so we return
		// a proxy object and defer the decision until later
		return ProxyFVector(this, name);

	}

	FValue &FVector::operator[](const FName& name) const {
		return get(name) + get(DEFAULT_NAME);
	}

  ostream& FVector::print(ostream& out) const {
    out << "{";
    for (const_iterator i = cbegin(); i != cend(); ++i) {
      FValue value = i->second;
      if (i->first != DEFAULT_NAME) {
        value += get(DEFAULT_NAME);
      }
      if (i->first != DEFAULT_NAME && i->second != 0.0) {
        out << i->first << "=" << value << ", ";
      }
    }
    out << "}";
    return out;
  }

  ostream& operator<<(ostream& out, const FVector& fv) {
    return fv.print(out);
  }

  const FValue& FVector::get(const FName& name) const {
    const_iterator fi = m_features.find(name);
    if (fi == m_features.end()) {
      return DEFAULT;
    } else {
      return fi->second;
    }
  }

  void FVector::set(const FName& name, const FValue& value) {
    m_features[name] = value;
  }

  FVector& FVector::operator+= (const FVector& rhs) {
    //default value will take care of itself here.
    for (iterator i = begin(); i != end(); ++i) {
      set(i->first,i->second + rhs.get(i->first));
    }
    for (const_iterator i = rhs.cbegin(); i != rhs.cend(); ++i) {
      if (!hasNonDefaultValue(i->first)) {
        set(i->first,i->second);
      }
    }
    return *this;
  }

  FVector& FVector::operator-= (const FVector& rhs) {
    for (iterator i = begin(); i != end(); ++i) {
      set(i->first,i->second - rhs.get(i->first));
    }
    for (const_iterator i = rhs.cbegin(); i != rhs.cend(); ++i) {
      if (!hasNonDefaultValue(i->first)) {
        set(i->first,-(i->second));
      }
    }
    return *this;
  }

  FVector& FVector::operator*= (const FVector& rhs) {
    FValue lhsDefault = get(DEFAULT_NAME);
    FValue rhsDefault = rhs.get(DEFAULT_NAME);
    for (iterator i = begin(); i != end(); ++i) {
      if (i->first == DEFAULT_NAME) {
        set(i->first,lhsDefault*rhsDefault);
      } else {
        FValue lhsValue = i->second;
        FValue rhsValue = rhs.get(i->first);
        set(i->first, lhsValue*rhsDefault + rhsValue*lhsDefault + lhsValue*rhsValue);
      }
    }
    if (lhsDefault) {
      //Features that have the default value in the lhs
      for (const_iterator i = rhs.cbegin(); i != rhs.cend(); ++i) {
        if (!hasNonDefaultValue(i->first)) {
          set(i->first, lhsDefault*i->second);
        }
      }
    }
    return *this;
  }

  FVector& FVector::operator/= (const FVector& rhs) {
    FValue lhsDefault = get(DEFAULT_NAME);
    FValue rhsDefault = rhs.get(DEFAULT_NAME);
    if (lhsDefault && !rhsDefault) {
      throw runtime_error("Attempt to divide feature vectors where lhs has default and rhs does not");
    }
    FValue quotientDefault = 0;
    if (rhsDefault) {
      quotientDefault = lhsDefault / rhsDefault;
    }
    for (iterator i = begin(); i != end(); ++i) {
      if (i->first == DEFAULT_NAME) {
        set(i->first, quotientDefault);
      } else {
        FValue lhsValue = i->second;
        FValue rhsValue = rhs.get(i->first);
        set(i->first, (lhsValue + lhsDefault) / (rhsValue + rhsDefault) - quotientDefault);
      }
    }
    if (lhsDefault) {
      //Features that have the default value in the lhs
      for (const_iterator i = rhs.cbegin(); i != rhs.cend(); ++i) {
        if (!hasNonDefaultValue(i->first)) {
          set(i->first, lhsDefault / (i->second + rhsDefault) - quotientDefault);
        }
      }
    }
    return *this;
  }

	FVector& FVector::max_equals(const FVector& rhs) {
		FValue lhsDefault = get(DEFAULT_NAME);
		FValue rhsDefault = rhs.get(DEFAULT_NAME);
		FValue maxDefault = max(lhsDefault,rhsDefault);
		for (iterator i = begin(); i != end(); ++i) {
			if (i->first == DEFAULT_NAME) {
				set(i->first, maxDefault);
			} else {
				set(i->first, max(i->second + lhsDefault, rhs.get(i->first) + rhsDefault) - maxDefault);
			}
		}
		for (const_iterator i = rhs.cbegin(); i != rhs.cend(); ++i) {
			if (!hasNonDefaultValue(i->first)) {
				set(i->first, max(lhsDefault, (i->second + rhsDefault)) - maxDefault);
			}
		}

		return *this;
	}

  FVector& FVector::operator+= (const FValue& rhs) {
    set(DEFAULT_NAME, get(DEFAULT_NAME) + rhs);
    return *this;
  }

  FVector& FVector::operator-= (const FValue& rhs) {
    set(DEFAULT_NAME, get(DEFAULT_NAME) - rhs);
    return *this;
  }

  FVector& FVector::operator*= (const FValue& rhs) {
    //NB Could do this with boost::bind ?
    //This multiplies the default value, which is what we want
    for (iterator i = begin(); i != end(); ++i) {
      i->second *= rhs;
    }
    return *this;
  }

  FVector& FVector::operator/= (const FValue& rhs) {
		//This dividess the default value, which is what we want
    for (iterator i = begin(); i != end(); ++i) {
      i->second /= rhs;
    }
    return *this;
  }

  FValue FVector::l1norm() const {
    FValue norm = 0;
    for (const_iterator i = cbegin(); i != cend(); ++i) {
      if (!(i->second) && i->first == DEFAULT_NAME) {
        throw runtime_error("Cannot take l1norm with non-zero default values");
      }
      norm += abs(i->second);
    }
    return norm;
  }

  FValue FVector::sum() const {
    FValue sum = 0;
    for (const_iterator i = cbegin(); i != cend(); ++i) {
      if (!(i->second) && i->first == DEFAULT_NAME) {
        throw runtime_error("Cannot take sum with non-zero default values");
      }
      sum += i->second;
    }
    return sum;
  }

  FValue FVector::l2norm() const {
    return sqrt(inner_product(*this));
  }

  FValue FVector::inner_product(const FVector& rhs) const {
    FValue lhsDefault = get(DEFAULT_NAME);
    FValue rhsDefault = rhs.get(DEFAULT_NAME);
    if (lhsDefault && rhsDefault) {
      throw runtime_error("Cannot take inner product if both lhs and rhs have non-zero default values");
    }
    FValue product = 0.0;
    for (const_iterator i = cbegin(); i != cend(); ++i) {
      if (i->first != DEFAULT_NAME) {
        product += ((i->second + lhsDefault)*(rhs.get(i->first) + rhsDefault));
      }
    }

    if (lhsDefault) {
      //Features that have the default value in the rhs
      for (const_iterator i = rhs.cbegin(); i != rhs.cend(); ++i) {
        if (!hasNonDefaultValue(i->first)) {
          product += (i->second + rhsDefault)*lhsDefault;
        }
      }
    }
    return product;
  }

  FValue FVector::inner_product(const std::vector<FValue>& rhs) const {
      assert(size() == rhs.size());
      const ScoreIndexManager &sim = StaticData::Instance().GetScoreIndexManager;
      FValue product = 0;
      if (get(DEFAULT_NAME) == 0) {
	  	  for (const_iterator i = cbegin(); i != cend(); i++) {
	      	  FValue rv = rhs[ sim.GetFeatureIndex(i->first) ];
	      	  product += i->second * rv;
      	  }
	  } else {
		  for (size_t i = 0; i < rhs.size(); i++) {
		      product += rhs[i] * get(sim.GetFeatureName(i));
		  }
      }
      return product;
  }

  const FVector operator+(const FVector& lhs, const FVector& rhs) {
    return FVector(lhs) += rhs;
  }

  const FVector operator-(const FVector& lhs, const FVector& rhs) {
    return FVector(lhs) -= rhs;
  }

	const FVector operator*(const FVector& lhs, const FVector& rhs) {
    return FVector(lhs) *= rhs;
  }

  const FVector operator/(const FVector& lhs, const FVector& rhs) {
    return FVector(lhs) /= rhs;
  }

  const FVector operator+(const FVector& lhs, const FValue& rhs) {
    return FVector(lhs) += rhs;
  }

  const FVector operator-(const FVector& lhs, const FValue& rhs) {
    return FVector(lhs) -= rhs;
  }

  const FVector operator*(const FVector& lhs, const FValue& rhs) {
    return FVector(lhs) *= rhs;
  }

  const FVector operator/(const FVector& lhs, const FValue& rhs) {
    return FVector(lhs) /= rhs;
  }

  const FVector fvmax(const FVector& lhs, const FVector& rhs) {
    return FVector(lhs).max_equals(rhs);
  }

  FValue inner_product(const FVector& lhs, const FVector& rhs) {
    if (lhs.size() >= rhs.size()) {
      return rhs.inner_product(lhs);
    } else {
      return lhs.inner_product(rhs);
    }
  }

}
<commit_msg>Fixing more bugs in FeatureVector.cpp.<commit_after>/*
 Moses - factored phrase-based language decoder
 Copyright (C) 2010 University of Edinburgh

 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License along
 with this program; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

 */

#include <algorithm>
#include <cassert>
#include <cmath>
#include <fstream>
#include <sstream>
#include <stdexcept>

#include "StaticData.h"
#include "ScoreIndexManager.h"
#include "FeatureVector.h"

using namespace std;

namespace Moses {

  const string FName::SEP = "_";
  FName::Name2Id FName::name2id;
  vector<string> FName::id2name;

  void FName::init(const string& name)  {
    Name2Id::iterator i = name2id.find(name);
    if (i != name2id.end()) {
      m_id = i->second;
    } else {
      m_id = name2id.size();
      name2id[name] = m_id;
      id2name.push_back(name);
    }
  }

  std::ostream& operator<<( std::ostream& out, const FName& name) {
    out << name.name();
    return out;
  }

  size_t FName::hash() const {
    /*std::size_t seed = 0;
		 boost::hash_combine(seed, m_root);
		 boost::hash_combine(seed, m_name);
		 return seed;*/
    return boost::hash_value(m_id);
  }

  const std::string& FName::name() const {
    return id2name[m_id];
  }

  bool FName::operator==(const FName& rhs) const {
    return m_id == rhs.m_id;
  }

  bool FName::operator!=(const FName& rhs) const {
    return ! (*this == rhs);
  }

	FVector::FVector(FValue defaultValue)  {
    m_features[DEFAULT_NAME] = defaultValue;
	}

	void FVector::clear() {
    m_features.clear();
    m_features[DEFAULT_NAME] = DEFAULT;
	}

	void FVector::load(const std::string& filename) {
		ifstream in (filename.c_str());
		if (!in) {
			ostringstream msg;
			msg << "Unable to open " << filename;
			throw runtime_error(msg.str());
		}
		string line;
		while(getline(in,line)) {
			if (line[0] == '#') continue;
			istringstream linestream(line);
			string namestring;
			FValue value;
			linestream >> namestring;
			linestream >> value;
			FName fname(namestring);
			set(fname,value);
		}
  }

  void FVector::save(const string& filename) const {
    ofstream out(filename.c_str());
    if (!out) {
      ostringstream msg;
      msg << "Unable to open " << filename;
      throw runtime_error(msg.str());
    }
    write(out);
    out.close();
  }

  void FVector::write(ostream& out) const {
    for (const_iterator i = cbegin(); i != cend(); ++i) {
      out << i->first << " " << i->second << endl;
    }
  }

  FName FVector::DEFAULT_NAME("DEFAULT","");
  const FValue FVector::DEFAULT = 0;

  static bool equalsTolerance(FValue lhs, FValue rhs) {
    if (lhs == rhs) return true;
    static const FValue TOLERANCE = 1e-4;
    FValue diff = abs(lhs-rhs);
    FValue mean = (abs(lhs)+abs(rhs))/2;
    //cerr << "ET " << lhs << " " << rhs << " " << diff << " " << mean << " " << endl;
    return diff/mean < TOLERANCE ;
  }

  bool FVector::operator== (const FVector& rhs) const {
    if (this == &rhs) {
      return true;
    }
    if (get(DEFAULT_NAME) != rhs.get(DEFAULT_NAME)) return false;
    for (const_iterator i  = cbegin(); i != cend(); ++i) {
      if (!equalsTolerance(i->second,rhs.get(i->first))) return false;
    }
    for (const_iterator i = rhs.cbegin(); i != rhs.cend(); ++i) {
      if (!equalsTolerance(i->second, get(i->first))) return false;
    }
    return true;
  }

  bool FVector::operator!= (const FVector& rhs) const {
    return ! (*this == rhs);
  }

	ProxyFVector FVector::operator[](const FName& name) {
		// At this point, we don't know whether operator[] was called, so we return
		// a proxy object and defer the decision until later
		return ProxyFVector(this, name);

	}

	FValue &FVector::operator[](const FName& name) const {
		return get(name) + get(DEFAULT_NAME);
	}

  ostream& FVector::print(ostream& out) const {
    out << "{";
    for (const_iterator i = cbegin(); i != cend(); ++i) {
      FValue value = i->second;
      if (i->first != DEFAULT_NAME) {
        value += get(DEFAULT_NAME);
      }
      if (i->first != DEFAULT_NAME && i->second != 0.0) {
        out << i->first << "=" << value << ", ";
      }
    }
    out << "}";
    return out;
  }

  ostream& operator<<(ostream& out, const FVector& fv) {
    return fv.print(out);
  }

  const FValue& FVector::get(const FName& name) const {
    const_iterator fi = m_features.find(name);
    if (fi == m_features.end()) {
      return DEFAULT;
    } else {
      return fi->second;
    }
  }

  void FVector::set(const FName& name, const FValue& value) {
    m_features[name] = value;
  }

  FVector& FVector::operator+= (const FVector& rhs) {
    //default value will take care of itself here.
    for (iterator i = begin(); i != end(); ++i) {
      set(i->first,i->second + rhs.get(i->first));
    }
    for (const_iterator i = rhs.cbegin(); i != rhs.cend(); ++i) {
      if (!hasNonDefaultValue(i->first)) {
        set(i->first,i->second);
      }
    }
    return *this;
  }

  FVector& FVector::operator-= (const FVector& rhs) {
    for (iterator i = begin(); i != end(); ++i) {
      set(i->first,i->second - rhs.get(i->first));
    }
    for (const_iterator i = rhs.cbegin(); i != rhs.cend(); ++i) {
      if (!hasNonDefaultValue(i->first)) {
        set(i->first,-(i->second));
      }
    }
    return *this;
  }

  FVector& FVector::operator*= (const FVector& rhs) {
    FValue lhsDefault = get(DEFAULT_NAME);
    FValue rhsDefault = rhs.get(DEFAULT_NAME);
    for (iterator i = begin(); i != end(); ++i) {
      if (i->first == DEFAULT_NAME) {
        set(i->first,lhsDefault*rhsDefault);
      } else {
        FValue lhsValue = i->second;
        FValue rhsValue = rhs.get(i->first);
        set(i->first, lhsValue*rhsDefault + rhsValue*lhsDefault + lhsValue*rhsValue);
      }
    }
    if (lhsDefault) {
      //Features that have the default value in the lhs
      for (const_iterator i = rhs.cbegin(); i != rhs.cend(); ++i) {
        if (!hasNonDefaultValue(i->first)) {
          set(i->first, lhsDefault*i->second);
        }
      }
    }
    return *this;
  }

  FVector& FVector::operator/= (const FVector& rhs) {
    FValue lhsDefault = get(DEFAULT_NAME);
    FValue rhsDefault = rhs.get(DEFAULT_NAME);
    if (lhsDefault && !rhsDefault) {
      throw runtime_error("Attempt to divide feature vectors where lhs has default and rhs does not");
    }
    FValue quotientDefault = 0;
    if (rhsDefault) {
      quotientDefault = lhsDefault / rhsDefault;
    }
    for (iterator i = begin(); i != end(); ++i) {
      if (i->first == DEFAULT_NAME) {
        set(i->first, quotientDefault);
      } else {
        FValue lhsValue = i->second;
        FValue rhsValue = rhs.get(i->first);
        set(i->first, (lhsValue + lhsDefault) / (rhsValue + rhsDefault) - quotientDefault);
      }
    }
    if (lhsDefault) {
      //Features that have the default value in the lhs
      for (const_iterator i = rhs.cbegin(); i != rhs.cend(); ++i) {
        if (!hasNonDefaultValue(i->first)) {
          set(i->first, lhsDefault / (i->second + rhsDefault) - quotientDefault);
        }
      }
    }
    return *this;
  }

	FVector& FVector::max_equals(const FVector& rhs) {
		FValue lhsDefault = get(DEFAULT_NAME);
		FValue rhsDefault = rhs.get(DEFAULT_NAME);
		FValue maxDefault = max(lhsDefault,rhsDefault);
		for (iterator i = begin(); i != end(); ++i) {
			if (i->first == DEFAULT_NAME) {
				set(i->first, maxDefault);
			} else {
				set(i->first, max(i->second + lhsDefault, rhs.get(i->first) + rhsDefault) - maxDefault);
			}
		}
		for (const_iterator i = rhs.cbegin(); i != rhs.cend(); ++i) {
			if (!hasNonDefaultValue(i->first)) {
				set(i->first, max(lhsDefault, (i->second + rhsDefault)) - maxDefault);
			}
		}

		return *this;
	}

  FVector& FVector::operator+= (const FValue& rhs) {
    set(DEFAULT_NAME, get(DEFAULT_NAME) + rhs);
    return *this;
  }

  FVector& FVector::operator-= (const FValue& rhs) {
    set(DEFAULT_NAME, get(DEFAULT_NAME) - rhs);
    return *this;
  }

  FVector& FVector::operator*= (const FValue& rhs) {
    //NB Could do this with boost::bind ?
    //This multiplies the default value, which is what we want
    for (iterator i = begin(); i != end(); ++i) {
      i->second *= rhs;
    }
    return *this;
  }

  FVector& FVector::operator/= (const FValue& rhs) {
		//This dividess the default value, which is what we want
    for (iterator i = begin(); i != end(); ++i) {
      i->second /= rhs;
    }
    return *this;
  }

  FValue FVector::l1norm() const {
    FValue norm = 0;
    for (const_iterator i = cbegin(); i != cend(); ++i) {
      if (!(i->second) && i->first == DEFAULT_NAME) {
        throw runtime_error("Cannot take l1norm with non-zero default values");
      }
      norm += abs(i->second);
    }
    return norm;
  }

  FValue FVector::sum() const {
    FValue sum = 0;
    for (const_iterator i = cbegin(); i != cend(); ++i) {
      if (!(i->second) && i->first == DEFAULT_NAME) {
        throw runtime_error("Cannot take sum with non-zero default values");
      }
      sum += i->second;
    }
    return sum;
  }

  FValue FVector::l2norm() const {
    return sqrt(inner_product(*this));
  }

  FValue FVector::inner_product(const FVector& rhs) const {
    FValue lhsDefault = get(DEFAULT_NAME);
    FValue rhsDefault = rhs.get(DEFAULT_NAME);
    if (lhsDefault && rhsDefault) {
      throw runtime_error("Cannot take inner product if both lhs and rhs have non-zero default values");
    }
    FValue product = 0.0;
    for (const_iterator i = cbegin(); i != cend(); ++i) {
      if (i->first != DEFAULT_NAME) {
        product += ((i->second + lhsDefault)*(rhs.get(i->first) + rhsDefault));
      }
    }

    if (lhsDefault) {
      //Features that have the default value in the rhs
      for (const_iterator i = rhs.cbegin(); i != rhs.cend(); ++i) {
        if (!hasNonDefaultValue(i->first)) {
          product += (i->second + rhsDefault)*lhsDefault;
        }
      }
    }
    return product;
  }

  FValue FVector::inner_product(const std::vector<FValue>& rhs) const {
      assert(size() == rhs.size());
      const ScoreIndexManager &sim = StaticData::Instance().GetScoreIndexManager();
      FValue product = 0;
      if (get(DEFAULT_NAME) == 0) {
	  	  for (const_iterator i = cbegin(); i != cend(); i++) {
	      	  FValue rv = rhs[ sim.GetFeatureIndex(i->first.name()) ];
	      	  product += i->second * rv;
      	  }
	  } else {
		  for (size_t i = 0; i < rhs.size(); i++) {
		      product += rhs[i] * get(sim.GetFeatureName(i));
		  }
      }
      return product;
  }

  const FVector operator+(const FVector& lhs, const FVector& rhs) {
    return FVector(lhs) += rhs;
  }

  const FVector operator-(const FVector& lhs, const FVector& rhs) {
    return FVector(lhs) -= rhs;
  }

	const FVector operator*(const FVector& lhs, const FVector& rhs) {
    return FVector(lhs) *= rhs;
  }

  const FVector operator/(const FVector& lhs, const FVector& rhs) {
    return FVector(lhs) /= rhs;
  }

  const FVector operator+(const FVector& lhs, const FValue& rhs) {
    return FVector(lhs) += rhs;
  }

  const FVector operator-(const FVector& lhs, const FValue& rhs) {
    return FVector(lhs) -= rhs;
  }

  const FVector operator*(const FVector& lhs, const FValue& rhs) {
    return FVector(lhs) *= rhs;
  }

  const FVector operator/(const FVector& lhs, const FValue& rhs) {
    return FVector(lhs) /= rhs;
  }

  const FVector fvmax(const FVector& lhs, const FVector& rhs) {
    return FVector(lhs).max_equals(rhs);
  }

  FValue inner_product(const FVector& lhs, const FVector& rhs) {
    if (lhs.size() >= rhs.size()) {
      return rhs.inner_product(lhs);
    } else {
      return lhs.inner_product(rhs);
    }
  }

}
<|endoftext|>


<commit_before>#include "rhs/rhs.h"
#include "defs.h"
#include "comp_funcs.h"
#include <cstring>
comp trap(comp * restr v, size_t s){
    comp sum = 0;
    for(size_t i=0; i < s-1; i++){
        sum += v[i];
    }
    sum *= 2;
    sum += v[0] + v[s-1];
    return sum;
}
double trap(double * restr v, size_t s){
    double sum = 0;
    for(size_t i=0; i < s-1; i++){
        sum += v[i];
    }
    sum *= 2;
    sum += v[0] + v[s-1];
    return sum;
}
rhs_CNLS::rhs_CNLS(size_t dimen, double g, double e, double _dt,
        double tlen, size_t n_steps):rhs(dimen), g0(g), e0(e), dt(_dt),
        LENGTH_T(tlen), NUM_TIME_STEPS(n_steps){
    u1 = (comp*)malloc(NUM_TIME_STEPS*sizeof(comp));
    u2 = (comp*)malloc(NUM_TIME_STEPS*sizeof(comp));
    comp_in = (comp*)malloc(NUM_TIME_STEPS*sizeof(comp));
    comp_out = (comp*)malloc(NUM_TIME_STEPS*sizeof(comp));
    comp_out_r = (comp*)malloc(NUM_TIME_STEPS*sizeof(comp));
    comp_in_r = (comp*)malloc(NUM_TIME_STEPS*sizeof(comp));
    sq1 = (double*)malloc(NUM_TIME_STEPS*sizeof(double));
    sq2 = (double*)malloc(NUM_TIME_STEPS*sizeof(double));
    k = (double*)malloc(NUM_TIME_STEPS*sizeof(double));
    ksq = (double*)malloc(NUM_TIME_STEPS*sizeof(double));
    //input arrays don't really matter here because the plan
    //is executated against specific input arrays at runtime
    //and not with the initialization arrays
    ffor=fftw_plan_dft_1d(NUM_TIME_STEPS, u1, u2,FFTW_FORWARD, FFTW_ESTIMATE);
    fback=fftw_plan_dft_1d(NUM_TIME_STEPS, comp_in, comp_out, FFTW_BACKWARD, FFTW_ESTIMATE);
    //create k values
    double mulval=(2.0*PI/LENGTH_T)*(NUM_TIME_STEPS/2.0);
    for(int i=0; i<NUM_TIME_STEPS/2; i++){
        k[i] = mulval * i;
        ksq[i] = k[i]*k[i];
    }
    for(int i=NUM_TIME_STEPS/2; i<NUM_TIME_STEPS; i++){
        k[i] = mulval * (i-NUM_TIME_STEPS);
        ksq[i] = k[i]*k[i];
    }
}
rhs_CNLS::~rhs_CNLS(){
    free(u1);
    free(u2);
    free(comp_in);
    free(comp_out);
    free(comp_in_r);
    free(comp_out_r);
    free(sq1);
    free(sq2);
    free(k);
    free(ksq);
    fftw_destroy_plan(ffor);
    fftw_destroy_plan(fback);
}
//This is the RHS for the CNLS equations
//I haven't implemented real ffts for the parts to which they apply
//since they have a more complicated output and I just want to have a working
//copy for now
int rhs_CNLS::dxdt(comp* restr x, comp* restr dx, double t){
    uf1=x;
    uf2=x+NUM_TIME_STEPS;

    //take the inverse fourier transform
    fftw_norm(fback, uf1, u1, NUM_TIME_STEPS);
    fftw_norm(fback, uf2, u2, NUM_TIME_STEPS);
    //normalize the u arrays

   // cout << endl;
    //do fancy math stuff
    for(size_t i = 0; i < NUM_TIME_STEPS; i++){
        sq1[i] = _sqabs(u1[i]);
        sq2[i] = _sqabs(u2[i]);
        comp_in_r[i] = sq1[i] + sq2[i];
    }
    comp expr1 = I*(2*g0/(1+trap(comp_in_r, NUM_TIME_STEPS)*dt/e0));
    //calculate the ffts for the rhs
    for(size_t i = 0; i < NUM_TIME_STEPS; i++){
        comp_in_r[i] = sq1[i] + A*sq2[i];
        comp_in[i] = u2[i] * u2[i] + _conj(u1[i]);
    }
    //fourier transform forwards nonlinear equations
    fftw_norm(ffor, comp_in, comp_out, NUM_TIME_STEPS);
    fftw_norm(ffor, comp_in_r, comp_out_r, NUM_TIME_STEPS);

    for(size_t i = 0; i < NUM_TIME_STEPS; i++){
        dx[i] = ((D/2) * ksq[i] + K) * uf1[i] - comp_out_r[i]*u1[i]
            - B*comp_out[i] + expr1*uf1[i]*(1-tau*ksq[i]) - Gamma*uf1[i];
    }
    //Do the fft work for the other half of the calculations

    for(size_t i = 0; i < NUM_TIME_STEPS; i++){
        comp_in_r[i] = A*sq1[i] + sq2[i];
        comp_in[i] = u1[i] * u1[i] + _conj(u2[i]);
    }
    fftw_norm(ffor, comp_in, comp_out, NUM_TIME_STEPS);
    fftw_norm(ffor, comp_in_r, comp_out_r, NUM_TIME_STEPS);
    for(size_t i = 0; i < NUM_TIME_STEPS; i++){
        dx[i+NUM_TIME_STEPS] = ((D/2) * ksq[i] + K) * uf2[i] - comp_out_r[i]*u2[i]
            - B*comp_out[i] + expr1*uf2[i]*(1-tau*ksq[i]) - Gamma*uf2[i];
    }
    for(size_t i = 0; i < NUM_TIME_STEPS; i++){
        cout << _real(dx[i]) << "+i" << _imag(dx[i]) <<
            ", " << _real(dx[i+NUM_TIME_STEPS]) << "+i"<<_imag(dx[i+NUM_TIME_STEPS])<<endl;
    }       //
    //all values have been set
    //return success code
    return 0;
}

<commit_msg>Fixed skyrocketing solutions<commit_after>#include "rhs/rhs.h"
#include "defs.h"
#include "comp_funcs.h"
#include <cstring>
comp trap(comp * restr v, size_t s){
    comp sum = 0;
    for(size_t i=0; i < s-1; i++){
        sum += v[i];
    }
    sum *= 2;
    sum += v[0] + v[s-1];
    return sum;
}
double trap(double * restr v, size_t s){
    double sum = 0;
    for(size_t i=0; i < s-1; i++){
        sum += v[i];
    }
    sum *= 2;
    sum += v[0] + v[s-1];
    return sum;
}
rhs_CNLS::rhs_CNLS(size_t dimen, double g, double e, double _dt,
        double tlen, size_t n_steps):rhs(dimen), g0(g), e0(e), dt(_dt),
        LENGTH_T(tlen), NUM_TIME_STEPS(n_steps){
    u1 = (comp*)malloc(NUM_TIME_STEPS*sizeof(comp));
    u2 = (comp*)malloc(NUM_TIME_STEPS*sizeof(comp));
    comp_in = (comp*)malloc(NUM_TIME_STEPS*sizeof(comp));
    comp_out = (comp*)malloc(NUM_TIME_STEPS*sizeof(comp));
    comp_out_r = (comp*)malloc(NUM_TIME_STEPS*sizeof(comp));
    comp_in_r = (comp*)malloc(NUM_TIME_STEPS*sizeof(comp));
    sq1 = (double*)malloc(NUM_TIME_STEPS*sizeof(double));
    sq2 = (double*)malloc(NUM_TIME_STEPS*sizeof(double));
    k = (double*)malloc(NUM_TIME_STEPS*sizeof(double));
    ksq = (double*)malloc(NUM_TIME_STEPS*sizeof(double));
    //input arrays don't really matter here because the plan
    //is executated against specific input arrays at runtime
    //and not with the initialization arrays
    ffor=fftw_plan_dft_1d(NUM_TIME_STEPS, u1, u2,FFTW_FORWARD, FFTW_ESTIMATE);
    fback=fftw_plan_dft_1d(NUM_TIME_STEPS, comp_in, comp_out, FFTW_BACKWARD, FFTW_ESTIMATE);
    //create k values
    double mulval=(2.0*PI/LENGTH_T)*(NUM_TIME_STEPS/2.0);
    cout << mulval << endl << endl;
    for(int i=0; i<NUM_TIME_STEPS/2; i++){
        k[i] = mulval * i;
        ksq[i] = k[i]*k[i];
    }
    for(int i=NUM_TIME_STEPS/2; i<NUM_TIME_STEPS; i++){
        k[i] = mulval * ((int)i-(int)NUM_TIME_STEPS);
        ksq[i] = k[i]*k[i];
    }
}
rhs_CNLS::~rhs_CNLS(){
    free(u1);
    free(u2);
    free(comp_in);
    free(comp_out);
    free(comp_in_r);
    free(comp_out_r);
    free(sq1);
    free(sq2);
    free(k);
    free(ksq);
    fftw_destroy_plan(ffor);
    fftw_destroy_plan(fback);
}
//This is the RHS for the CNLS equations
//I haven't implemented real ffts for the parts to which they apply
//since they have a more complicated output and I just want to have a working
//copy for now
int rhs_CNLS::dxdt(comp* restr x, comp* restr dx, double t){
    uf1=x;
    uf2=x+NUM_TIME_STEPS;

    //take the inverse fourier transform
    fftw_norm(fback, uf1, u1, NUM_TIME_STEPS);
    fftw_norm(fback, uf2, u2, NUM_TIME_STEPS);
    //normalize the u arrays

   // cout << endl;
    //do fancy math stuff
    for(size_t i = 0; i < NUM_TIME_STEPS; i++){
        sq1[i] = _sqabs(u1[i]);
        sq2[i] = _sqabs(u2[i]);
        comp_in_r[i] = sq1[i] + sq2[i];
    }
    comp expr1 = I*(2*g0/(1+trap(comp_in_r, NUM_TIME_STEPS)*dt/e0));
    //calculate the ffts for the rhs
    for(size_t i = 0; i < NUM_TIME_STEPS; i++){
        comp_in_r[i] = sq1[i] + A*sq2[i];
        comp_in[i] = u2[i] * u2[i] + _conj(u1[i]);
    }
    //fourier transform forwards nonlinear equations
    fftw_norm(ffor, comp_in, comp_out, NUM_TIME_STEPS);
    fftw_norm(ffor, comp_in_r, comp_out_r, NUM_TIME_STEPS);

    for(size_t i = 0; i < NUM_TIME_STEPS; i++){
        dx[i] = ((D/2) * ksq[i] + K) * uf1[i] - comp_out_r[i]*u1[i]
            - B*comp_out[i] + expr1*uf1[i]*(1-tau*ksq[i]) - Gamma*uf1[i];
    }
    //Do the fft work for the other half of the calculations

    for(size_t i = 0; i < NUM_TIME_STEPS; i++){
        comp_in_r[i] = A*sq1[i] + sq2[i];
        comp_in[i] = u1[i] * u1[i] + _conj(u2[i]);
    }
    fftw_norm(ffor, comp_in, comp_out, NUM_TIME_STEPS);
    fftw_norm(ffor, comp_in_r, comp_out_r, NUM_TIME_STEPS);
    for(int i = 0; i < NUM_TIME_STEPS; i++){
        cout << k[i] << " " << ksq[i] << endl;
    }
    for(size_t i = 0; i < NUM_TIME_STEPS; i++){
        dx[i+NUM_TIME_STEPS] = ((D/2) * ksq[i] + K) * uf2[i] - comp_out_r[i]*u2[i]
            - B*comp_out[i] + expr1*uf2[i]*(1-tau*ksq[i]) - Gamma*uf2[i];
    }
    cout << "RHS output values" << endl;
    cout << "real(u)   imag(u)   real(v)   imag(v)" << endl;
    for(size_t i = 0; i < NUM_TIME_STEPS; i++){
        cout << _real(dx[i]) << "+i" << _imag(dx[i]) <<
            ", " << _real(dx[i+NUM_TIME_STEPS]) << "+i"<<_imag(dx[i+NUM_TIME_STEPS])<<endl;
    }       //
    //all values have been set
    //return success code
    return 0;
}

<|endoftext|>


<commit_before>/* This file is part of the KDE project

   Copyright (C) 1999, 2000 Rik Hemsley <rik@kde.org>
             (C) 1999, 2000 Wilco Greven <j.w.greven@student.utwente.nl>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.
*/

#include <iostream>

#include <qstring.h>
#include <qstrlist.h>

#include <RMM_Token.h>
#include <RMM_Enum.h>
#include <RMM_Address.h>
#include <RMM_Defines.h>

using namespace RMM;

RAddress::RAddress()
    :   RHeaderBody()
{
    // Empty.
}

RAddress::RAddress(const RAddress & addr)
    :   RHeaderBody     (addr),
        mailboxList_    (addr.mailboxList_),
        name_           (addr.name_),
        phrase_         (addr.phrase_)
{
    // Empty.
}

RAddress::RAddress(const QCString & addr)
    :   RHeaderBody(addr)
{
    // Empty.
}

RAddress::~RAddress()
{
    // Empty.
}

    RAddress &
RAddress::operator = (const RAddress & addr)
{
    if (this == &addr) return *this; // Don't do a = a.

    mailboxList_    = addr.mailboxList_;
    name_           = addr.name_;
    phrase_         = addr.phrase_;

    RHeaderBody::operator = (addr);

    return *this;
}

    RAddress &
RAddress::operator = (const QCString & s)
{
    RHeaderBody::operator = (s);
    return *this;
}

    bool
RAddress::operator == (RAddress & a)
{
    parse();
    a.parse();

    bool ok(false);

    if (a.type() == RAddress::Mailbox) {

        ok = (name_ == a.name_ && phrase_ == a.phrase_);

    } else {
        // TODO
        qDebug("Not implemented !");
    }

    return ok;
}

    void
RAddress::_parse()
{
    QCString s = strRep_.stripWhiteSpace();

    // RFC822: group: phrase ":" [#mailbox] ";"
    // -> If a group, MUST end in ";".

    if (s.right(1) == ";") { // This is a group !

        // TODO
        rmmDebug("I'm a group.");
        rmmDebug("Not implemented !");

    } else {

        RMailbox m(s);
        // XXX Is this necessary ?
        // m.parse();
        mailboxList_.append(m);
    }
}

    void
RAddress::_assemble()
{
    if (type() == RAddress::Group) {

        // TODO
        rmmDebug("assembling group not implemented");

    } else {

        strRep_ = mailboxList_.at(0)->asString();
    }
}

    void
RAddress::createDefault()
{
    mailboxList_.clear();
    RMailbox m;
    m.createDefault();
    mailboxList_.append(m);
    assembled_ = true;
}

    RAddress::Type
RAddress::type()
{
    parse();
    return name_.isEmpty() ? Mailbox : Group;
}

    QDataStream &
RMM::operator >> (QDataStream & s, RMM::RAddress & addr)
{
    unsigned int count;

    s   >> addr.name_
        >> addr.phrase_
        >> count;

    for (unsigned int i = 0; i < count; i++) {
        RMailbox m;
        s >> m;
        addr.mailboxList_.append(m);
    }

    addr.parsed_ = true;
    addr.assembled_ = false;

    return s;
}

    QDataStream &
RMM::operator << (QDataStream & s, RMM::RAddress & addr)
{
    addr.parse();

    s   << addr.name_
        << addr.phrase_
        << (unsigned int)(addr.mailboxList_.count());

    QValueList<RMailbox>::Iterator it;

    for (it = addr.mailboxList_.begin(); it != addr.mailboxList_.end(); ++it)
        s << *it;

    return s;
}

    QCString
RAddress::phrase()
{
    parse();
    RMailbox m(*(mailboxList_.at(0)));
    return m.phrase();
}

    void
RAddress::setPhrase(const QCString & s)
{
    parse();
    (*(mailboxList_.at(0))).setPhrase(s);
}

    QCString
RAddress::route()
{
    parse();
    RMailbox m(*(mailboxList_.at(0)));
    return m.route();
}

    void
RAddress::setRoute(const QCString & s)
{
    parse();
    (*(mailboxList_.at(0))).setRoute(s);
}

    QCString
RAddress::localPart()
{
    parse();
    RMailbox m(*(mailboxList_.at(0)));
    return m.localPart();
}

    void
RAddress::setLocalPart(const QCString & s)
{
    parse();
    (*(mailboxList_.at(0))).setLocalPart(s);
}

    QCString
RAddress::domain()
{
    parse();
    RMailbox m(*(mailboxList_.at(0)));
    return m.domain();
}

    void
RAddress::setDomain(const QCString & s)
{
    parse();
    (*(mailboxList_.at(0))).setDomain(s);
}

   QCString
RAddress::name()
{
    parse();
    return name_;
}

    void
RAddress::setName(const QCString & s)
{
    parse();
    name_ = s;
}

    QValueList<RMailbox>
RAddress::mailboxList()
{
    parse();
    return mailboxList_;
}

// vim:ts=4:sw=4:tw=78
<commit_msg>make it compile<commit_after>/* This file is part of the KDE project

   Copyright (C) 1999, 2000 Rik Hemsley <rik@kde.org>
             (C) 1999, 2000 Wilco Greven <j.w.greven@student.utwente.nl>

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Library General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; see the file COPYING.LIB.  If not, write to
   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
   Boston, MA 02111-1307, USA.
*/

#include <iostream>

#include <qstring.h>
#include <qstrlist.h>

#include <RMM_Token.h>
#include <RMM_Enum.h>
#include <RMM_Address.h>
#include <RMM_Defines.h>

using namespace RMM;

RAddress::RAddress()
    :   RHeaderBody()
{
    // Empty.
}

RAddress::RAddress(const RAddress & addr)
    :   RHeaderBody     (addr),
        mailboxList_    (addr.mailboxList_),
        name_           (addr.name_),
        phrase_         (addr.phrase_)
{
    // Empty.
}

RAddress::RAddress(const QCString & addr)
    :   RHeaderBody(addr)
{
    // Empty.
}

RAddress::~RAddress()
{
    // Empty.
}

    RAddress &
RAddress::operator = (const RAddress & addr)
{
    if (this == &addr) return *this; // Don't do a = a.

    mailboxList_    = addr.mailboxList_;
    name_           = addr.name_;
    phrase_         = addr.phrase_;

    RHeaderBody::operator = (addr);

    return *this;
}

    RAddress &
RAddress::operator = (const QCString & s)
{
    RHeaderBody::operator = (s);
    return *this;
}

    bool
RAddress::operator == (RAddress & a)
{
    parse();
    a.parse();

    bool ok(false);

    if (a.type() == RAddress::Mailbox) {

        ok = (name_ == a.name_ && phrase_ == a.phrase_);

    } else {
        // TODO
        qDebug("Not implemented !");
    }

    return ok;
}

    void
RAddress::_parse()
{
    QCString s = strRep_.stripWhiteSpace();

    // RFC822: group: phrase ":" [#mailbox] ";"
    // -> If a group, MUST end in ";".

    if (s.right(1) == ";") { // This is a group !

        // TODO
        rmmDebug("I'm a group.");
        rmmDebug("Not implemented !");

    } else {

        RMailbox m(s);
        // XXX Is this necessary ?
        // m.parse();
        mailboxList_.append(m);
    }
}

    void
RAddress::_assemble()
{
    if (type() == RAddress::Group) {

        // TODO
        rmmDebug("assembling group not implemented");

    } else {

        strRep_ = (*mailboxList_.at(0)).asString();
    }
}

    void
RAddress::createDefault()
{
    mailboxList_.clear();
    RMailbox m;
    m.createDefault();
    mailboxList_.append(m);
    assembled_ = true;
}

    RAddress::Type
RAddress::type()
{
    parse();
    return name_.isEmpty() ? Mailbox : Group;
}

    QDataStream &
RMM::operator >> (QDataStream & s, RMM::RAddress & addr)
{
    unsigned int count;

    s   >> addr.name_
        >> addr.phrase_
        >> count;

    for (unsigned int i = 0; i < count; i++) {
        RMailbox m;
        s >> m;
        addr.mailboxList_.append(m);
    }

    addr.parsed_ = true;
    addr.assembled_ = false;

    return s;
}

    QDataStream &
RMM::operator << (QDataStream & s, RMM::RAddress & addr)
{
    addr.parse();

    s   << addr.name_
        << addr.phrase_
        << (unsigned int)(addr.mailboxList_.count());

    QValueList<RMailbox>::Iterator it;

    for (it = addr.mailboxList_.begin(); it != addr.mailboxList_.end(); ++it)
        s << *it;

    return s;
}

    QCString
RAddress::phrase()
{
    parse();
    RMailbox m(*(mailboxList_.at(0)));
    return m.phrase();
}

    void
RAddress::setPhrase(const QCString & s)
{
    parse();
    (*(mailboxList_.at(0))).setPhrase(s);
}

    QCString
RAddress::route()
{
    parse();
    RMailbox m(*(mailboxList_.at(0)));
    return m.route();
}

    void
RAddress::setRoute(const QCString & s)
{
    parse();
    (*(mailboxList_.at(0))).setRoute(s);
}

    QCString
RAddress::localPart()
{
    parse();
    RMailbox m(*(mailboxList_.at(0)));
    return m.localPart();
}

    void
RAddress::setLocalPart(const QCString & s)
{
    parse();
    (*(mailboxList_.at(0))).setLocalPart(s);
}

    QCString
RAddress::domain()
{
    parse();
    RMailbox m(*(mailboxList_.at(0)));
    return m.domain();
}

    void
RAddress::setDomain(const QCString & s)
{
    parse();
    (*(mailboxList_.at(0))).setDomain(s);
}

   QCString
RAddress::name()
{
    parse();
    return name_;
}

    void
RAddress::setName(const QCString & s)
{
    parse();
    name_ = s;
}

    QValueList<RMailbox>
RAddress::mailboxList()
{
    parse();
    return mailboxList_;
}

// vim:ts=4:sw=4:tw=78
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkOutputWindow.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-2000 Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/
#include "vtkOutputWindow.h"
#ifdef _WIN32
#include "vtkWin32OutputWindow.h"
#endif
#include "vtkObjectFactory.h"

vtkOutputWindow* vtkOutputWindow::Instance = 0;
vtkOutputWindowSmartPointer vtkOutputWindow::SmartPointer(NULL);

void vtkOutputWindowDisplayText(const char* message)
{
  vtkOutputWindow::GetInstance()->DisplayText(message);
}

vtkOutputWindowSmartPointer::~vtkOutputWindowSmartPointer()
{
  if (Pointer)
    {
    Pointer->Delete();
    }
}

vtkOutputWindow::vtkOutputWindow()
{
  this->PromptUser = 0;
}

vtkOutputWindow::~vtkOutputWindow()
{
  vtkOutputWindow::Instance = 0;
}

void vtkOutputWindow::PrintSelf(ostream& os, vtkIndent indent)
{
  this->vtkObject::PrintSelf(os, indent);

  os << indent << "vtkOutputWindow Single instance = "
     << (void*)vtkOutputWindow::Instance << endl;
  os << indent << "Prompt User: "
     << (this->PromptUser ? "On\n" : "Off\n");
}

// default implementation outputs to cerr only
void vtkOutputWindow::DisplayText(const char* txt)
{
  cerr << txt;
  if (this->PromptUser)
    {
    char c = 'n';
    cerr << "\nDo you want to suppress any further messages (y,n,q)?."
              << endl;
    cin >> c;
    if (c == 'y')
      {
      vtkObject::GlobalWarningDisplayOff();
      }
    if(c == 'q')
      {
      this->PromptUser = false;
      }
    }
}

// Up the reference count so it behaves like New
vtkOutputWindow* vtkOutputWindow::New()
{
  vtkOutputWindow* ret = vtkOutputWindow::GetInstance();
  ret->Register(NULL);
  return ret;
}

// Return the single instance of the vtkOutputWindow
vtkOutputWindow* vtkOutputWindow::GetInstance()
{
  if(!vtkOutputWindow::Instance)
    {
    // Try the factory first
    vtkOutputWindow::Instance = (vtkOutputWindow*)
      vtkObjectFactory::CreateInstance("vtkOutputWindow");
    // if the factory did not provide one, then create it here
    if(!vtkOutputWindow::Instance)
      {
#ifdef _WIN32
      vtkOutputWindow::Instance = vtkWin32OutputWindow::New();
#else
      vtkOutputWindow::Instance = new vtkOutputWindow;
#endif
      }
    // set the smart pointer to the instance, so
    // it will be UnRegister'ed at exit of the program
    vtkOutputWindow::SmartPointer.SetPointer(vtkOutputWindow::Instance );
    }
  // return the instance
  return vtkOutputWindow::Instance;
}

void vtkOutputWindow::SetInstance(vtkOutputWindow* instance)
{
  if (vtkOutputWindow::Instance==instance)
    {
    return;
    }
  vtkOutputWindow::SmartPointer.SetPointer( instance );
  // preferably this will be NULL
  if (vtkOutputWindow::Instance)
    {
    vtkOutputWindow::Instance->Delete();;
    }
  vtkOutputWindow::Instance = instance;
  // Should be safe to send a message now as instance is set
  if (instance->GetReferenceCount()!=1)
    {
    vtkGenericWarningMacro(<<"OutputWindow should have reference count = 1");
    }
  // user will call ->Delete() after setting instance
  instance->Register(NULL);
}

<commit_msg>BUG: remove the use of flase<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkOutputWindow.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

Copyright (c) 1993-2000 Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

 * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names
   of any contributors may be used to endorse or promote products derived
   from this software without specific prior written permission.

 * Modified source versions must be plainly marked as such, and must not be
   misrepresented as being the original software.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

=========================================================================*/
#include "vtkOutputWindow.h"
#ifdef _WIN32
#include "vtkWin32OutputWindow.h"
#endif
#include "vtkObjectFactory.h"

vtkOutputWindow* vtkOutputWindow::Instance = 0;
vtkOutputWindowSmartPointer vtkOutputWindow::SmartPointer(NULL);

void vtkOutputWindowDisplayText(const char* message)
{
  vtkOutputWindow::GetInstance()->DisplayText(message);
}

vtkOutputWindowSmartPointer::~vtkOutputWindowSmartPointer()
{
  if (Pointer)
    {
    Pointer->Delete();
    }
}

vtkOutputWindow::vtkOutputWindow()
{
  this->PromptUser = 0;
}

vtkOutputWindow::~vtkOutputWindow()
{
  vtkOutputWindow::Instance = 0;
}

void vtkOutputWindow::PrintSelf(ostream& os, vtkIndent indent)
{
  this->vtkObject::PrintSelf(os, indent);

  os << indent << "vtkOutputWindow Single instance = "
     << (void*)vtkOutputWindow::Instance << endl;
  os << indent << "Prompt User: "
     << (this->PromptUser ? "On\n" : "Off\n");
}

// default implementation outputs to cerr only
void vtkOutputWindow::DisplayText(const char* txt)
{
  cerr << txt;
  if (this->PromptUser)
    {
    char c = 'n';
    cerr << "\nDo you want to suppress any further messages (y,n,q)?."
              << endl;
    cin >> c;
    if (c == 'y')
      {
      vtkObject::GlobalWarningDisplayOff();
      }
    if(c == 'q')
      {
      this->PromptUser = 0;
      }
    }
}

// Up the reference count so it behaves like New
vtkOutputWindow* vtkOutputWindow::New()
{
  vtkOutputWindow* ret = vtkOutputWindow::GetInstance();
  ret->Register(NULL);
  return ret;
}

// Return the single instance of the vtkOutputWindow
vtkOutputWindow* vtkOutputWindow::GetInstance()
{
  if(!vtkOutputWindow::Instance)
    {
    // Try the factory first
    vtkOutputWindow::Instance = (vtkOutputWindow*)
      vtkObjectFactory::CreateInstance("vtkOutputWindow");
    // if the factory did not provide one, then create it here
    if(!vtkOutputWindow::Instance)
      {
#ifdef _WIN32
      vtkOutputWindow::Instance = vtkWin32OutputWindow::New();
#else
      vtkOutputWindow::Instance = new vtkOutputWindow;
#endif
      }
    // set the smart pointer to the instance, so
    // it will be UnRegister'ed at exit of the program
    vtkOutputWindow::SmartPointer.SetPointer(vtkOutputWindow::Instance );
    }
  // return the instance
  return vtkOutputWindow::Instance;
}

void vtkOutputWindow::SetInstance(vtkOutputWindow* instance)
{
  if (vtkOutputWindow::Instance==instance)
    {
    return;
    }
  vtkOutputWindow::SmartPointer.SetPointer( instance );
  // preferably this will be NULL
  if (vtkOutputWindow::Instance)
    {
    vtkOutputWindow::Instance->Delete();;
    }
  vtkOutputWindow::Instance = instance;
  // Should be safe to send a message now as instance is set
  if (instance->GetReferenceCount()!=1)
    {
    vtkGenericWarningMacro(<<"OutputWindow should have reference count = 1");
    }
  // user will call ->Delete() after setting instance
  instance->Register(NULL);
}

<|endoftext|>


<commit_before><commit_msg>Add <iterator> to the list of include files.  This is required for back_inserter.<commit_after><|endoftext|>


<commit_before>#include "settings.h"
#include "core/fs/os_file.h"
#include "core/log.h"
#include "debug/debug.h"
#include "imgui/imgui.h"
#include "platform_interface.h"
#include "utils.h"
#include <cstdio>
#include <lua.hpp>

static const char SETTINGS_PATH[] = "studio.ini";
static Settings* g_instance = nullptr;

static void shortcutInput(int& shortcut)
{
	StringBuilder<50> popup_name("");
	popup_name << (Lumix::int64)&shortcut;

	char key_string[30];
	PlatformInterface::getKeyName(shortcut, key_string, 30);

	StringBuilder<50> button_label(key_string);
	button_label << "###" << (Lumix::int64)&shortcut;

	if (ImGui::Button(button_label, ImVec2(50, 0))) shortcut = -1;

	auto& io = ImGui::GetIO();
	if (ImGui::IsItemHovered())
	{
		for (int i = 0; i < Lumix::lengthOf(ImGui::GetIO().KeysDown); ++i)
		{
			if (io.KeysDown[i])
			{
				shortcut = i;
				break;
			}
		}
	}
}

static int getIntegerField(lua_State* L, const char* name, int default_value)
{
	int value = default_value;
	if (lua_getfield(L, -1, name) == LUA_TNUMBER)
	{
		value = (int)lua_tointeger(L, -1);
	}
	lua_pop(L, 1);
	return value;
}

static bool getBoolean(lua_State* L, const char* name, bool default_value)
{
	bool value = default_value;
	if (lua_getglobal(L, name) == LUA_TBOOLEAN)
	{
		value = lua_toboolean(L, -1) != 0;
	}
	lua_pop(L, 1);
	return value;
}

static int getInteger(lua_State* L, const char* name, int default_value)
{
	int value = default_value;
	if (lua_getglobal(L, name) == LUA_TNUMBER)
	{
		value = (int)lua_tointeger(L, -1);
	}
	lua_pop(L, 1);
	return value;
}

Settings::Settings(Lumix::IAllocator& allocator)
	: m_allocator(allocator)
{
	ASSERT(!g_instance);
	g_instance = this;
	m_filter[0] = 0;
	m_is_maximized = true;
	m_window.x = m_window.y = 0;
	m_window.w = m_window.h = -1;
	m_is_entity_list_opened = false;
	m_is_entity_template_list_opened = false;
	m_is_asset_browser_opened = false;
	m_is_log_opened = false;
	m_is_profiler_opened = false;
	m_is_properties_opened = false;
	m_is_crash_reporting_enabled = true;

	m_autosave_time = 300;

	m_state = luaL_newstate();
	luaL_openlibs(m_state);
	lua_newtable(m_state);
	lua_setglobal(m_state, "custom");
}

Settings::~Settings()
{
	g_instance = nullptr;
	lua_close(m_state);
}

bool Settings::load(Action** actions, int actions_count)
{
	auto L = m_state;
	bool errors = luaL_loadfile(L, SETTINGS_PATH) != LUA_OK;
	errors = errors || lua_pcall(L, 0, LUA_MULTRET, 0) != LUA_OK;
	if (errors)
	{
		Lumix::g_log_error.log("lua") << SETTINGS_PATH << ": " << lua_tostring(L, -1);
		lua_pop(L, 1);
		return false;
	}

	if (lua_getglobal(L, "window") == LUA_TTABLE)
	{
		m_window.x = getIntegerField(L, "x", 0);
		m_window.y = getIntegerField(L, "y", 0);
		m_window.w = getIntegerField(L, "w", -1);
		m_window.h = getIntegerField(L, "h", -1);
	}
	lua_pop(L, 1);

	m_is_maximized = getBoolean(L, "maximized", true);

	m_is_opened = getBoolean(L, "settings_opened", false);
	m_is_asset_browser_opened = getBoolean(L, "asset_browser_opened", false);
	m_is_entity_list_opened = getBoolean(L, "entity_list_opened", false);
	m_is_entity_template_list_opened = getBoolean(L, "entity_template_list_opened", false);
	m_is_log_opened = getBoolean(L, "log_opened", false);
	m_is_profiler_opened = getBoolean(L, "profiler_opened", false);
	m_is_properties_opened = getBoolean(L, "properties_opened", false);
	m_is_crash_reporting_enabled = getBoolean(L, "error_reporting_enabled", true);
	Lumix::enableCrashReporting(m_is_crash_reporting_enabled);
	m_autosave_time = getInteger(L, "autosave_time", 300);

	if (lua_getglobal(L, "actions") == LUA_TTABLE)
	{
		for (int i = 0; i < actions_count; ++i)
		{
			if (lua_getfield(L, -1, actions[i]->name) == LUA_TTABLE)
			{
				for (int j = 0; j < Lumix::lengthOf(actions[i]->shortcut); ++j)
				{
					if (lua_rawgeti(L, -1, 1 + j) == LUA_TNUMBER)
					{
						actions[i]->shortcut[j] = (int)lua_tointeger(L, -1);
					}
					lua_pop(L, 1);
				}
			}
			lua_pop(L, 1);
		}
	}
	lua_pop(L, 1);

	ImGui::LoadDock(L);
	return true;
}

void Settings::setValue(const char* name, bool value)
{
	lua_getglobal(m_state, "custom");
	lua_pushboolean(m_state, value);
	lua_setfield(m_state, -2, name);
}

void Settings::setValue(const char* name, int value)
{
	lua_getglobal(m_state, "custom");
	lua_pushinteger(m_state, value);
	lua_setfield(m_state, -2, name);
}

int Settings::getValue(const char* name, int default_value) const
{
	lua_getglobal(m_state, "custom");
	int v = getIntegerField(m_state, name, default_value);
	lua_pop(m_state, 1);
	return v;
}

bool Settings::getValue(const char* name, bool default_value) const
{
	bool v = default_value;
	lua_getglobal(m_state, "custom");
	if (lua_getfield(m_state, -1, name) == LUA_TBOOLEAN)
	{
		v = lua_toboolean(m_state, -1) != 0;
	}
	lua_pop(m_state, 2);
	return v;
}

Settings* Settings::getInstance()
{
	return g_instance;
}

bool Settings::save(Action** actions, int actions_count)
{
	Lumix::FS::OsFile file;
	if (!file.open(SETTINGS_PATH, Lumix::FS::Mode::WRITE | Lumix::FS::Mode::CREATE, m_allocator)) return false;

	file << "window = { x = " << m_window.x
		<< ", y = " << m_window.y
		<< ", w = " << m_window.w
		<< ", h = " << m_window.h << " }\n";

	file << "maximized = " << (m_is_maximized ? "true" : "false") << "\n";

	auto writeBool = [&file](const char* name, bool value) {
		file << name << " = " << (value ? "true\n" : "false\n");
	};

	writeBool("settings_opened", m_is_opened);
	writeBool("asset_browser_opened", m_is_asset_browser_opened);
	writeBool("entity_list_opened", m_is_entity_list_opened);
	writeBool("entity_template_list_opened", m_is_entity_template_list_opened);
	writeBool("log_opened", m_is_log_opened);
	writeBool("profiler_opened", m_is_profiler_opened);
	writeBool("properties_opened", m_is_properties_opened);
	writeBool("error_reporting_enabled", m_is_crash_reporting_enabled);
	file << "autosave_time = " << m_autosave_time << "\n";

	file << "custom = {\n";
	lua_getglobal(m_state, "custom");
	lua_pushnil(m_state);
	bool first = true;
	while (lua_next(m_state, -2))
	{
		if (!first) file << ",\n";
		const char* name = lua_tostring(m_state, -2);
		switch (lua_type(m_state, -1))
		{
			case LUA_TBOOLEAN:
				file << name << " = " << (lua_toboolean(m_state, -1) != 0 ? "true" : "false");
				break;
			case LUA_TNUMBER:
				file << name << " = " << (int)lua_tonumber(m_state, -1);
				break;
			default:
				ASSERT(false);
				break;
		}
		lua_pop(m_state, 1);
		first = false;
	}
	lua_pop(m_state, 1);
	file << "}\n";

	file << "actions = {\n";
	for (int i = 0; i < actions_count; ++i)
	{
		file << "\t" << actions[i]->name << " = {"
			<< actions[i]->shortcut[0] << ", "
			<< actions[i]->shortcut[1] << ", "
			<< actions[i]->shortcut[2] << "},\n";
	}
	file << "}\n";

	ImGui::SaveDock(file);

	file.close();

	return true;
}

void Settings::showShortcutSettings(Action** actions, int actions_count)
{
	ImGui::InputText("Filter", m_filter, Lumix::lengthOf(m_filter));
	ImGui::Columns(4);
	for (int i = 0; i < actions_count; ++i)
	{
		Action& a = *actions[i];
		if (m_filter[0] == 0 || Lumix::stristr(a.label, m_filter) != 0)
		{
			ImGui::Text(a.label);
			ImGui::NextColumn();
			shortcutInput(a.shortcut[0]);
			ImGui::NextColumn();
			shortcutInput(a.shortcut[1]);
			ImGui::NextColumn();
			shortcutInput(a.shortcut[2]);
			ImGui::NextColumn();
		}
	}
	ImGui::Columns(1);
}

void Settings::onGUI(Action** actions, int actions_count)
{
	if (ImGui::BeginDock("Settings", &m_is_opened))
	{
		if (ImGui::Button("Save")) save(actions, actions_count);
		ImGui::SameLine();
		if (ImGui::Button("Reload")) load(actions, actions_count);
		ImGui::SameLine();
		ImGui::Text("Settings are saved when the application closes");

		ImGui::DragInt("Autosave time (seconds)", &m_autosave_time);
		if (ImGui::Checkbox("Crash reporting", &m_is_crash_reporting_enabled))
		{
			Lumix::enableCrashReporting(m_is_crash_reporting_enabled);
		}

		if (ImGui::CollapsingHeader("Shortcuts")) showShortcutSettings(actions, actions_count);

		ImGui::ShowStyleEditor();
	}
	ImGui::EndDock();
}
<commit_msg>fixed crash when changing pipeline parameters too much<commit_after>#include "settings.h"
#include "core/fs/os_file.h"
#include "core/log.h"
#include "debug/debug.h"
#include "imgui/imgui.h"
#include "platform_interface.h"
#include "utils.h"
#include <cstdio>
#include <lua.hpp>

static const char SETTINGS_PATH[] = "studio.ini";
static Settings* g_instance = nullptr;

static void shortcutInput(int& shortcut)
{
	StringBuilder<50> popup_name("");
	popup_name << (Lumix::int64)&shortcut;

	char key_string[30];
	PlatformInterface::getKeyName(shortcut, key_string, 30);

	StringBuilder<50> button_label(key_string);
	button_label << "###" << (Lumix::int64)&shortcut;

	if (ImGui::Button(button_label, ImVec2(50, 0))) shortcut = -1;

	auto& io = ImGui::GetIO();
	if (ImGui::IsItemHovered())
	{
		for (int i = 0; i < Lumix::lengthOf(ImGui::GetIO().KeysDown); ++i)
		{
			if (io.KeysDown[i])
			{
				shortcut = i;
				break;
			}
		}
	}
}

static int getIntegerField(lua_State* L, const char* name, int default_value)
{
	int value = default_value;
	if (lua_getfield(L, -1, name) == LUA_TNUMBER)
	{
		value = (int)lua_tointeger(L, -1);
	}
	lua_pop(L, 1);
	return value;
}

static bool getBoolean(lua_State* L, const char* name, bool default_value)
{
	bool value = default_value;
	if (lua_getglobal(L, name) == LUA_TBOOLEAN)
	{
		value = lua_toboolean(L, -1) != 0;
	}
	lua_pop(L, 1);
	return value;
}

static int getInteger(lua_State* L, const char* name, int default_value)
{
	int value = default_value;
	if (lua_getglobal(L, name) == LUA_TNUMBER)
	{
		value = (int)lua_tointeger(L, -1);
	}
	lua_pop(L, 1);
	return value;
}

Settings::Settings(Lumix::IAllocator& allocator)
	: m_allocator(allocator)
{
	ASSERT(!g_instance);
	g_instance = this;
	m_filter[0] = 0;
	m_is_maximized = true;
	m_window.x = m_window.y = 0;
	m_window.w = m_window.h = -1;
	m_is_entity_list_opened = false;
	m_is_entity_template_list_opened = false;
	m_is_asset_browser_opened = false;
	m_is_log_opened = false;
	m_is_profiler_opened = false;
	m_is_properties_opened = false;
	m_is_crash_reporting_enabled = true;

	m_autosave_time = 300;

	m_state = luaL_newstate();
	luaL_openlibs(m_state);
	lua_newtable(m_state);
	lua_setglobal(m_state, "custom");
}

Settings::~Settings()
{
	g_instance = nullptr;
	lua_close(m_state);
}

bool Settings::load(Action** actions, int actions_count)
{
	auto L = m_state;
	bool errors = luaL_loadfile(L, SETTINGS_PATH) != LUA_OK;
	errors = errors || lua_pcall(L, 0, LUA_MULTRET, 0) != LUA_OK;
	if (errors)
	{
		Lumix::g_log_error.log("lua") << SETTINGS_PATH << ": " << lua_tostring(L, -1);
		lua_pop(L, 1);
		return false;
	}

	if (lua_getglobal(L, "window") == LUA_TTABLE)
	{
		m_window.x = getIntegerField(L, "x", 0);
		m_window.y = getIntegerField(L, "y", 0);
		m_window.w = getIntegerField(L, "w", -1);
		m_window.h = getIntegerField(L, "h", -1);
	}
	lua_pop(L, 1);

	m_is_maximized = getBoolean(L, "maximized", true);

	m_is_opened = getBoolean(L, "settings_opened", false);
	m_is_asset_browser_opened = getBoolean(L, "asset_browser_opened", false);
	m_is_entity_list_opened = getBoolean(L, "entity_list_opened", false);
	m_is_entity_template_list_opened = getBoolean(L, "entity_template_list_opened", false);
	m_is_log_opened = getBoolean(L, "log_opened", false);
	m_is_profiler_opened = getBoolean(L, "profiler_opened", false);
	m_is_properties_opened = getBoolean(L, "properties_opened", false);
	m_is_crash_reporting_enabled = getBoolean(L, "error_reporting_enabled", true);
	Lumix::enableCrashReporting(m_is_crash_reporting_enabled);
	m_autosave_time = getInteger(L, "autosave_time", 300);

	if (lua_getglobal(L, "actions") == LUA_TTABLE)
	{
		for (int i = 0; i < actions_count; ++i)
		{
			if (lua_getfield(L, -1, actions[i]->name) == LUA_TTABLE)
			{
				for (int j = 0; j < Lumix::lengthOf(actions[i]->shortcut); ++j)
				{
					if (lua_rawgeti(L, -1, 1 + j) == LUA_TNUMBER)
					{
						actions[i]->shortcut[j] = (int)lua_tointeger(L, -1);
					}
					lua_pop(L, 1);
				}
			}
			lua_pop(L, 1);
		}
	}
	lua_pop(L, 1);

	ImGui::LoadDock(L);
	return true;
}

void Settings::setValue(const char* name, bool value)
{
	lua_getglobal(m_state, "custom");
	lua_pushboolean(m_state, value);
	lua_setfield(m_state, -2, name);
	lua_pop(m_state, 1);
}

void Settings::setValue(const char* name, int value)
{
	lua_getglobal(m_state, "custom");
	lua_pushinteger(m_state, value);
	lua_setfield(m_state, -2, name);
	lua_pop(m_state, 1);
}

int Settings::getValue(const char* name, int default_value) const
{
	lua_getglobal(m_state, "custom");
	int v = getIntegerField(m_state, name, default_value);
	lua_pop(m_state, 1);
	return v;
}

bool Settings::getValue(const char* name, bool default_value) const
{
	bool v = default_value;
	lua_getglobal(m_state, "custom");
	if (lua_getfield(m_state, -1, name) == LUA_TBOOLEAN)
	{
		v = lua_toboolean(m_state, -1) != 0;
	}
	lua_pop(m_state, 2);
	return v;
}

Settings* Settings::getInstance()
{
	return g_instance;
}

bool Settings::save(Action** actions, int actions_count)
{
	Lumix::FS::OsFile file;
	if (!file.open(SETTINGS_PATH, Lumix::FS::Mode::WRITE | Lumix::FS::Mode::CREATE, m_allocator)) return false;

	file << "window = { x = " << m_window.x
		<< ", y = " << m_window.y
		<< ", w = " << m_window.w
		<< ", h = " << m_window.h << " }\n";

	file << "maximized = " << (m_is_maximized ? "true" : "false") << "\n";

	auto writeBool = [&file](const char* name, bool value) {
		file << name << " = " << (value ? "true\n" : "false\n");
	};

	writeBool("settings_opened", m_is_opened);
	writeBool("asset_browser_opened", m_is_asset_browser_opened);
	writeBool("entity_list_opened", m_is_entity_list_opened);
	writeBool("entity_template_list_opened", m_is_entity_template_list_opened);
	writeBool("log_opened", m_is_log_opened);
	writeBool("profiler_opened", m_is_profiler_opened);
	writeBool("properties_opened", m_is_properties_opened);
	writeBool("error_reporting_enabled", m_is_crash_reporting_enabled);
	file << "autosave_time = " << m_autosave_time << "\n";

	file << "custom = {\n";
	lua_getglobal(m_state, "custom");
	lua_pushnil(m_state);
	bool first = true;
	while (lua_next(m_state, -2))
	{
		if (!first) file << ",\n";
		const char* name = lua_tostring(m_state, -2);
		switch (lua_type(m_state, -1))
		{
			case LUA_TBOOLEAN:
				file << name << " = " << (lua_toboolean(m_state, -1) != 0 ? "true" : "false");
				break;
			case LUA_TNUMBER:
				file << name << " = " << (int)lua_tonumber(m_state, -1);
				break;
			default:
				ASSERT(false);
				break;
		}
		lua_pop(m_state, 1);
		first = false;
	}
	lua_pop(m_state, 1);
	file << "}\n";

	file << "actions = {\n";
	for (int i = 0; i < actions_count; ++i)
	{
		file << "\t" << actions[i]->name << " = {"
			<< actions[i]->shortcut[0] << ", "
			<< actions[i]->shortcut[1] << ", "
			<< actions[i]->shortcut[2] << "},\n";
	}
	file << "}\n";

	ImGui::SaveDock(file);

	file.close();

	return true;
}

void Settings::showShortcutSettings(Action** actions, int actions_count)
{
	ImGui::InputText("Filter", m_filter, Lumix::lengthOf(m_filter));
	ImGui::Columns(4);
	for (int i = 0; i < actions_count; ++i)
	{
		Action& a = *actions[i];
		if (m_filter[0] == 0 || Lumix::stristr(a.label, m_filter) != 0)
		{
			ImGui::Text(a.label);
			ImGui::NextColumn();
			shortcutInput(a.shortcut[0]);
			ImGui::NextColumn();
			shortcutInput(a.shortcut[1]);
			ImGui::NextColumn();
			shortcutInput(a.shortcut[2]);
			ImGui::NextColumn();
		}
	}
	ImGui::Columns(1);
}

void Settings::onGUI(Action** actions, int actions_count)
{
	if (ImGui::BeginDock("Settings", &m_is_opened))
	{
		if (ImGui::Button("Save")) save(actions, actions_count);
		ImGui::SameLine();
		if (ImGui::Button("Reload")) load(actions, actions_count);
		ImGui::SameLine();
		ImGui::Text("Settings are saved when the application closes");

		ImGui::DragInt("Autosave time (seconds)", &m_autosave_time);
		if (ImGui::Checkbox("Crash reporting", &m_is_crash_reporting_enabled))
		{
			Lumix::enableCrashReporting(m_is_crash_reporting_enabled);
		}

		if (ImGui::CollapsingHeader("Shortcuts")) showShortcutSettings(actions, actions_count);

		ImGui::ShowStyleEditor();
	}
	ImGui::EndDock();
}
<|endoftext|>


<commit_before>#include <elf/oid.h>
#include <elf/memory.h>
#include <elf/time.h>
#include <elf/rand.h>
#include <elf/matchmaking.h>

namespace elf {

    enum MatchRank {
        ROOKIE_RANK = 800,
        MASTER_RANK = 2500,
        RANK_OFFSET = 100,
    };

    int get_rank_level(int rank) {
        if (rank <= ROOKIE_RANK) {
            return ROOKIE_RANK;
        } else if (rank > MASTER_RANK) {
            return MASTER_RANK;
        }
        return rank - rank % RANK_OFFSET;
    }

    struct MatchEntity {
        oid_t id;
        int elo;
        int status;
        int size;
        int camp;
        time_t time;

        std::list<MatchEntity> members;

        int get_size() {
            if (members.empty()) {
                return size;
            }
            int total = 0;
            std::list<MatchEntity>::iterator itr;
            for (itr = members.begin(); itr != members.end(); ++itr) {
                total += (*itr).get_size();
            }
            return total;
        }

        void get_members(TeamSet &memset) {
            if (members.empty()) {
                memset.insert(id);
                return;
            }
            std::list<MatchEntity>::iterator itr;
            for (itr = members.begin(); itr != members.end(); ++itr) {
                (*itr).get_members(memset);
            }
        }

        ~MatchEntity() {}
    };

    typedef std::map<int, TeamSet> rank_map_t;
    struct MatchQueue {
        int size_type;
        std::deque<oid_t> candidates;
        rank_map_t ranks;
    };

    std::map<int, MatchPool*> MatchPool::s_pools;

    MatchPool::MatchPool()
        : _type(0)
        , _team_size(0)
        , _camp_size(0) {
    }

    MatchPool::MatchPool(int type, int mode, int team_size, int camp_size)
        : _type(type)
        , _mode(mode)
        , _team_size(team_size)
        , _camp_size(camp_size) {
    }

    MatchPool::~MatchPool() {
        for (std::map<oid_t, MatchEntity*>::iterator itr = _entities.begin();
                itr != _entities.end();
                ++itr) {
            E_DELETE itr->second;
        }
        _entities.clear();

        for (std::map<int, MatchQueue*>::iterator itr = _queues.begin();
                itr != _queues.end();
                ++ itr) {
            E_DELETE itr->second;
        }

        _queues.clear();
    }

    MatchEntity *MatchPool::get_entity(const oid_t &id) {
        std::map<oid_t, MatchEntity*>::iterator itr = _entities.find(id);
        if (itr == _entities.end()) {
            return NULL;
        }
        return itr->second;
    }

    MatchEntity MatchPool::clone_entity(MatchEntity *src) {
        MatchEntity dst;
        dst = *src;
        return dst;
    }

    bool MatchPool::Push(int elo, int size, oid_t id) {
        MatchEntity *ent = NULL;
        std::map<oid_t, MatchEntity*>::iterator itr = _entities.find(id);
        if (itr == _entities.end()) {
            ent = E_NEW MatchEntity;
        } else {
            ent = itr->second;
            if (ent == NULL) {
                ent = E_NEW MatchEntity;
            } else if (ent->status == MATCH_PENDING) {
                return false;
            }
        }

        ent->id = id;
        ent->elo = elo;
        ent->time = time_s();
        ent->status = MATCH_PENDING;
        ent->size = size;

        push(ent);
        return true;
    }

    void  MatchPool::push(MatchEntity *ent) {
        _entities[ent->id] = ent;

        std::map<int, MatchQueue*>::iterator itr = _queues.find(ent->size);
        MatchQueue *que;
        if (itr == _queues.end()) {
            que = E_NEW MatchQueue;
            que->size_type = ent->size;
            _queues[ent->size] = que;
        } else {
            que = itr->second;
        }
        que->candidates.push_back(ent->id);

        int lvl = get_rank_level(ent->elo);
        rank_map_t::iterator itr_rank = que->ranks.find(lvl);
        if (itr_rank == que->ranks.end()) {
            que->ranks.insert(std::make_pair(lvl, TeamSet()));
        }
        que->ranks[lvl].insert(ent->id);
    }

    bool MatchPool::top(MatchEntity &ent, int size_type) {
        std::map<int, MatchQueue*>::iterator itr = _queues.find(size_type);
        if (itr == _queues.end()) {
            return false;
        }
        MatchQueue *que = itr->second;
        if (que->candidates.empty()) {
            return false;
        }

        std::deque<oid_t>::iterator i_que = que->candidates.begin();
        for (;i_que != que->candidates.end(); ++i_que) {
            MatchEntity *curr = get_entity(*i_que);
            if (curr && curr->status == MATCH_PENDING) {
                curr->status = MATCH_DONE;
                //ent = clone_entity(curr);
                ent.members.push_back(clone_entity(curr));
                ent.size = size_type;
                return true;
            }
        }
        return false;
    }

    /// find skill proper opponent
    bool MatchPool::get_opponent(MatchEntity *ent, MatchEntity *opp, int need_size) {
        bool ret = false;
        switch (_mode) {
        case MATCH_MOD_RAND:
            ret = get_opponent_rand(ent, opp, need_size);
            break;
        case MATCH_MOD_ELO:
            ret = get_opponent_elo(ent, opp, need_size);
            break;
        }
        return ret;
    }

    bool MatchPool::get_opponent_elo(MatchEntity *ent, MatchEntity *opp, int need_size) {
        return false;
    }

    bool MatchPool::get_opponent_rand(MatchEntity *ent, MatchEntity *opp, int need_size) {
        return get_entity_rand(need_size, opp);
    }

    bool MatchPool::get_entity_rand(int need_size, MatchEntity *dst) {
        int size = 0;
        for (int i = need_size;i >= 1; i--) {
            std::map<int, MatchQueue*>::iterator itr = _queues.find(i);
            if (itr == _queues.end()) {
                continue;
            }
            MatchQueue *que = itr->second;
            if (que == NULL || que->size_type > need_size - size) {
                continue;
            }

            // rand
            std::deque<oid_t>::iterator itr_c = que->candidates.begin();
            std::vector<oid_t> candidates;
            for (;itr_c != que->candidates.end(); ++itr_c) {
                MatchEntity *curr = get_entity(*itr_c);
                if (curr != NULL && curr->status == MATCH_PENDING) {
                    candidates.push_back(*itr_c);
                }
            }

            int size_type = que->size_type;
            if (candidates.size() == 0 ||
                candidates.size() < size_t((need_size - size) / size_type)) {
                continue;
            }
            int total = candidates.size();
            while (size + size_type <= need_size) {
                int idx = rand(0, total - 1);
                MatchEntity *curr = get_entity(candidates[idx]);
                if (curr != NULL && curr->status == MATCH_PENDING) {
                    curr->status = MATCH_DONE;
                    dst->members.push_back(clone_entity(curr));
                    size += size_type;
                }
            }
            if (size == need_size) {
                break;
            }
        }
        return size == need_size;
    }

    bool MatchPool::get_buddy(int need_size, MatchEntity *dst) {
        bool ret = false;
        switch (_mode) {
        case MATCH_MOD_RAND:
            ret = get_buddy_rand(need_size, dst);
            break;
        case MATCH_MOD_ELO:
            ret = get_buddy_elo(need_size, dst);
            break;
        }
        return ret;
    }

    bool MatchPool::get_buddy_elo(int need_size, MatchEntity *dst) {
        return NULL;
    }

    bool MatchPool::get_buddy_rand(int need_size, MatchEntity *dst) {
        return get_entity_rand(need_size, dst);
    }

    bool MatchPool::pop(int size_type, MatchRes &res) {
        std::vector<MatchEntity*> camps;
        for (int i = 0;i < _camp_size; i++) {
            MatchEntity *ent = E_NEW MatchEntity;
            ent->camp = i;
            camps.push_back(ent);
        }

        int success = pop(size_type, camps);

        // merge result
        res.type = _type;
        for (size_t i = 0;i < camps.size(); i++) {
            TeamSet members;
            camps[i]->get_members(members);
            if (!success) {
                // restore
                TeamSet::iterator itr = members.begin();
                for (;itr != members.end(); ++itr) {
                    MatchEntity *ent = get_entity(*itr);
                    if (ent) {
                        ent->status = MATCH_PENDING;
                    }
                }
            } else {
                res.teams.push_back(members);
            }
            E_DELETE camps[i];
        }

        return success;
    }

    bool MatchPool::pop(int size_type, std::vector<MatchEntity*> &camps) {
        if (camps.size() != size_t(_camp_size)) {
            return false;
        }

        // find entity for first camp
        MatchEntity *ent = camps[0];
        if (!top(*ent, size_type)) {
            return false;
        }

        // find others' camp members with size_type
        for (size_t i = 1;i < camps.size(); i++) {
            MatchEntity *opp = camps[i];
            if (!get_opponent(ent, opp, ent->size)) {
                return false;
            }
        }

        // find left members
        int size = ent->get_size();
        while (size < _team_size) {
            // find buddies
            if (!get_buddy(_team_size - size, camps[0])) {
                return false;
            }

            // find oppoents
            for (size_t i = 1;i < camps.size(); i++) {
                if (!get_opponent(camps[0], camps[i], _team_size - size)) {
                    return false;
                }
            }
            size += camps[0]->get_size();
        }
        return true;
    }

    /// tick
    bool MatchPool::tick(std::list<MatchRes> &resList) {
        bool ret = pop(resList);

        // adjust ranklevel for entities and gc.
        std::map<oid_t, MatchEntity*>::iterator itr = _entities.begin();
        for (;itr != _entities.end();) {
            MatchEntity *ent = itr->second;
            if (ent == NULL || ent->status != MATCH_PENDING) {
                if (ret) {
                    if (ent != NULL) {
                        E_DELETE ent;
                    }
                    _entities.erase(itr++);
                } else {
                    ent->status = MATCH_PENDING;
                }
            } else {
                ++itr;
            }
        }

        return  ret;
    }

    /// pop matched team(s)
    bool MatchPool::pop(std::list<MatchRes> &resList) {
        for (int i = _team_size;i >= 1; i--) {
            MatchRes res;
            if (pop(i, res)) {
                resList.push_back(res);
            }
        }
        return !resList.empty();
    }

    void MatchPool::Del(const oid_t &id) {
        std::map<oid_t, MatchEntity*>::iterator itr = _entities.find(id);
        if (itr != _entities.end()) {
            MatchEntity *ent = itr->second;
            ent->status = MatchPool::MATCH_DELETED;
        }
    }

    MatchPool *MatchPool::Create(int type, int mode, int team_size, int camp_size) {
        MatchPool *pool = Get(type);
        if (pool != NULL) {
            return pool;
        }
        pool = E_NEW MatchPool(type, mode, team_size, camp_size);
        s_pools[type] = pool;
        return pool;
    }

    MatchPool *MatchPool::Get(int type) {
        std::map<int, MatchPool*>::iterator itr = s_pools.find(type);
        MatchPool *pool = NULL;
        if (itr != s_pools.end()) {
            pool = itr->second;
        }
        return pool;
    }

    void MatchPool::Proc(std::list<MatchRes> &resList) {
        std::map<int, MatchPool*>::iterator itr;
        for (itr = s_pools.begin(); itr != s_pools.end(); ++itr) {
            std::list<MatchRes> tmpList;;
            if (itr->second->tick(tmpList)) {
                resList.merge(tmpList);
            }
        }
    }

    void MatchPool::Cancel(oid_t id) {
        std::map<int, MatchPool*>::iterator itr;
        for (itr = s_pools.begin(); itr != s_pools.end(); ++itr) {
            itr->second->Del(id);
        }
    }

    void MatchPool::Release() {
        std::map<int, MatchPool*>::iterator itr;
        for (itr = s_pools.begin(); itr != s_pools.end(); ++itr) {
            E_DELETE itr->second;
        }
        s_pools.clear();
    }

} // namespace MatchMaking
<commit_msg>[MOD] matchmaking<commit_after>#include <elf/oid.h>
#include <elf/memory.h>
#include <elf/time.h>
#include <elf/rand.h>
#include <elf/matchmaking.h>

namespace elf {

    enum MatchRank {
        ROOKIE_RANK = 800,
        MASTER_RANK = 2500,
        RANK_OFFSET = 100,
    };

    int get_rank_level(int rank) {
        if (rank <= ROOKIE_RANK) {
            return ROOKIE_RANK;
        } else if (rank > MASTER_RANK) {
            return MASTER_RANK;
        }
        return rank - rank % RANK_OFFSET;
    }

    struct MatchEntity {
        oid_t id;
        int elo;
        int status;
        int size;
        int camp;
        time_t time;

        std::list<MatchEntity> members;

        int get_size() {
            if (members.empty()) {
                return size;
            }
            int total = 0;
            std::list<MatchEntity>::iterator itr;
            for (itr = members.begin(); itr != members.end(); ++itr) {
                total += (*itr).get_size();
            }
            return total;
        }

        void get_members(TeamSet &memset) {
            if (members.empty()) {
                memset.insert(id);
                return;
            }
            std::list<MatchEntity>::iterator itr;
            for (itr = members.begin(); itr != members.end(); ++itr) {
                (*itr).get_members(memset);
            }
        }

        ~MatchEntity() {}
    };

    typedef std::map<int, TeamSet> rank_map_t;
    struct MatchQueue {
        int size_type;
        std::deque<oid_t> candidates;
        rank_map_t ranks;
    };

    std::map<int, MatchPool*> MatchPool::s_pools;

    MatchPool::MatchPool()
        : _type(0)
        , _team_size(0)
        , _camp_size(0) {
    }

    MatchPool::MatchPool(int type, int mode, int team_size, int camp_size)
        : _type(type)
        , _mode(mode)
        , _team_size(team_size)
        , _camp_size(camp_size) {
    }

    MatchPool::~MatchPool() {
        for (std::map<oid_t, MatchEntity*>::iterator itr = _entities.begin();
                itr != _entities.end();
                ++itr) {
            E_DELETE itr->second;
        }
        _entities.clear();

        for (std::map<int, MatchQueue*>::iterator itr = _queues.begin();
                itr != _queues.end();
                ++ itr) {
            E_DELETE itr->second;
        }

        _queues.clear();
    }

    MatchEntity *MatchPool::get_entity(const oid_t &id) {
        std::map<oid_t, MatchEntity*>::iterator itr = _entities.find(id);
        if (itr == _entities.end()) {
            return NULL;
        }
        return itr->second;
    }

    MatchEntity MatchPool::clone_entity(MatchEntity *src) {
        MatchEntity dst;
        dst = *src;
        return dst;
    }

    bool MatchPool::Push(int elo, int size, oid_t id) {
        MatchEntity *ent = NULL;
        std::map<oid_t, MatchEntity*>::iterator itr = _entities.find(id);
        if (itr == _entities.end()) {
            ent = E_NEW MatchEntity;
        } else {
            ent = itr->second;
            if (ent == NULL) {
                ent = E_NEW MatchEntity;
            } else if (ent->status == MATCH_PENDING) {
                return false;
            }
        }

        ent->id = id;
        ent->elo = elo;
        ent->time = time_s();
        ent->status = MATCH_PENDING;
        ent->size = size;

        push(ent);
        return true;
    }

    void  MatchPool::push(MatchEntity *ent) {
        _entities[ent->id] = ent;

        std::map<int, MatchQueue*>::iterator itr = _queues.find(ent->size);
        MatchQueue *que;
        if (itr == _queues.end()) {
            que = E_NEW MatchQueue;
            que->size_type = ent->size;
            _queues[ent->size] = que;
        } else {
            que = itr->second;
        }
        que->candidates.push_back(ent->id);

        int lvl = get_rank_level(ent->elo);
        rank_map_t::iterator itr_rank = que->ranks.find(lvl);
        if (itr_rank == que->ranks.end()) {
            que->ranks.insert(std::make_pair(lvl, TeamSet()));
        }
        que->ranks[lvl].insert(ent->id);
    }

    bool MatchPool::top(MatchEntity &ent, int size_type) {
        std::map<int, MatchQueue*>::iterator itr = _queues.find(size_type);
        if (itr == _queues.end()) {
            return false;
        }
        MatchQueue *que = itr->second;
        if (que->candidates.empty()) {
            return false;
        }

        std::deque<oid_t>::iterator i_que = que->candidates.begin();
        for (;i_que != que->candidates.end(); ++i_que) {
            MatchEntity *curr = get_entity(*i_que);
            if (curr && curr->status == MATCH_PENDING) {
                curr->status = MATCH_DONE;
                //ent = clone_entity(curr);
                ent.members.push_back(clone_entity(curr));
                ent.size = size_type;
                return true;
            }
        }
        return false;
    }

    /// find skill proper opponent
    bool MatchPool::get_opponent(MatchEntity *ent, MatchEntity *opp, int need_size) {
        bool ret = false;
        switch (_mode) {
        case MATCH_MOD_RAND:
            ret = get_opponent_rand(ent, opp, need_size);
            break;
        case MATCH_MOD_ELO:
            ret = get_opponent_elo(ent, opp, need_size);
            break;
        }
        return ret;
    }

    bool MatchPool::get_opponent_elo(MatchEntity *ent, MatchEntity *opp, int need_size) {
        return false;
    }

    bool MatchPool::get_opponent_rand(MatchEntity *ent, MatchEntity *opp, int need_size) {
        return get_entity_rand(need_size, opp);
    }

    bool MatchPool::get_entity_rand(int need_size, MatchEntity *dst) {
        int size = 0;
        for (int i = need_size;i >= 1; i--) {
            std::map<int, MatchQueue*>::iterator itr = _queues.find(i);
            if (itr == _queues.end()) {
                continue;
            }
            MatchQueue *que = itr->second;
            if (que == NULL || que->size_type > need_size - size) {
                continue;
            }

            // rand
            std::deque<oid_t>::iterator itr_c = que->candidates.begin();
            std::vector<oid_t> candidates;
            for (;itr_c != que->candidates.end(); ++itr_c) {
                MatchEntity *curr = get_entity(*itr_c);
                if (curr != NULL && curr->status == MATCH_PENDING) {
                    candidates.push_back(*itr_c);
                }
            }

            int size_type = que->size_type;
            if (candidates.size() == 0 ||
                candidates.size() < size_t((need_size - size) / size_type)) {
                continue;
            }
            int total = candidates.size();
            while (size + size_type <= need_size) {
                int idx = rand(0, total - 1);
                MatchEntity *curr = get_entity(candidates[idx]);
                if (curr != NULL && curr->status == MATCH_PENDING) {
                    curr->status = MATCH_DONE;
                    dst->members.push_back(clone_entity(curr));
                    size += size_type;
                }
            }
            if (size == need_size) {
                break;
            }
        }
        return size == need_size;
    }

    bool MatchPool::get_buddy(int need_size, MatchEntity *dst) {
        bool ret = false;
        switch (_mode) {
        case MATCH_MOD_RAND:
            ret = get_buddy_rand(need_size, dst);
            break;
        case MATCH_MOD_ELO:
            ret = get_buddy_elo(need_size, dst);
            break;
        }
        return ret;
    }

    bool MatchPool::get_buddy_elo(int need_size, MatchEntity *dst) {
        return NULL;
    }

    bool MatchPool::get_buddy_rand(int need_size, MatchEntity *dst) {
        return get_entity_rand(need_size, dst);
    }

    bool MatchPool::pop(int size_type, MatchRes &res) {
        std::vector<MatchEntity*> camps;
        for (int i = 0;i < _camp_size; i++) {
            MatchEntity *ent = E_NEW MatchEntity;
            ent->camp = i;
            camps.push_back(ent);
        }

        int success = pop(size_type, camps);

        // merge result
        res.type = _type;
        for (size_t i = 0;i < camps.size(); i++) {
            TeamSet members;
            camps[i]->get_members(members);
            if (!success) {
                // restore
                TeamSet::iterator itr = members.begin();
                for (;itr != members.end(); ++itr) {
                    MatchEntity *ent = get_entity(*itr);
                    if (ent) {
                        ent->status = MATCH_PENDING;
                    }
                }
            } else {
                res.teams.push_back(members);
            }
            E_DELETE camps[i];
        }

        return success;
    }

    bool MatchPool::pop(int size_type, std::vector<MatchEntity*> &camps) {
        if (camps.size() != size_t(_camp_size)) {
            return false;
        }

        // find entity for first camp
        MatchEntity *ent = camps[0];
        if (!top(*ent, size_type)) {
            return false;
        }

        // find others' camp members with size_type
        for (size_t i = 1;i < camps.size(); i++) {
            MatchEntity *opp = camps[i];
            if (!get_opponent(ent, opp, ent->size)) {
                return false;
            }
        }

        // find left members
        int size = ent->get_size();
        while (size < _team_size) {
            // find buddies
            if (!get_buddy(_team_size - size, camps[0])) {
                return false;
            }

            // find oppoents
            for (size_t i = 1;i < camps.size(); i++) {
                if (!get_opponent(camps[0], camps[i], _team_size - size)) {
                    return false;
                }
            }
            size += camps[0]->get_size();
        }
        return true;
    }

    /// tick
    bool MatchPool::tick(std::list<MatchRes> &resList) {
        bool ret = pop(resList);

        // adjust ranklevel for entities and gc.
        std::map<oid_t, MatchEntity*>::iterator itr = _entities.begin();
        for (;itr != _entities.end();) {
            MatchEntity *ent = itr->second;
            if (ent == NULL) {
                _entities.erase(itr++);
            } else {
                if (ent->status == MATCH_DELETED) {
                    E_DELETE ent;
                    _entities.erase(itr++);
                } else if (ent->status == MATCH_DONE) {
                    if (ret) {
                        if (ent != NULL) {
                            E_DELETE ent;
                        }
                        _entities.erase(itr++);
                    } else {
                        ent->status = MATCH_PENDING;
                        ++itr;
                    }
                } else {
                    ++itr;
                }
            }
        }

        return  ret;
    }

    /// pop matched team(s)
    bool MatchPool::pop(std::list<MatchRes> &resList) {
        for (int i = _team_size;i >= 1; i--) {
            MatchRes res;
            if (pop(i, res)) {
                resList.push_back(res);
            }
        }
        return !resList.empty();
    }

    void MatchPool::Del(const oid_t &id) {
        std::map<oid_t, MatchEntity*>::iterator itr = _entities.find(id);
        if (itr != _entities.end()) {
            MatchEntity *ent = itr->second;
            ent->status = MatchPool::MATCH_DELETED;
        }
    }

    MatchPool *MatchPool::Create(int type, int mode, int team_size, int camp_size) {
        MatchPool *pool = Get(type);
        if (pool != NULL) {
            return pool;
        }
        pool = E_NEW MatchPool(type, mode, team_size, camp_size);
        s_pools[type] = pool;
        return pool;
    }

    MatchPool *MatchPool::Get(int type) {
        std::map<int, MatchPool*>::iterator itr = s_pools.find(type);
        MatchPool *pool = NULL;
        if (itr != s_pools.end()) {
            pool = itr->second;
        }
        return pool;
    }

    void MatchPool::Proc(std::list<MatchRes> &resList) {
        std::map<int, MatchPool*>::iterator itr;
        for (itr = s_pools.begin(); itr != s_pools.end(); ++itr) {
            std::list<MatchRes> tmpList;;
            if (itr->second->tick(tmpList)) {
                resList.merge(tmpList);
            }
        }
    }

    void MatchPool::Cancel(oid_t id) {
        std::map<int, MatchPool*>::iterator itr;
        for (itr = s_pools.begin(); itr != s_pools.end(); ++itr) {
            itr->second->Del(id);
        }
    }

    void MatchPool::Release() {
        std::map<int, MatchPool*>::iterator itr;
        for (itr = s_pools.begin(); itr != s_pools.end(); ++itr) {
            E_DELETE itr->second;
        }
        s_pools.clear();
    }

} // namespace MatchMaking
<|endoftext|>


<commit_before>#ifndef ENTT_ENTITY_FWD_HPP
#define ENTT_ENTITY_FWD_HPP

#include "../config/config.h"

namespace entt {

/*! @brief Forward declaration of the registry class. */
template <typename>
class basic_registry;

/*! @brief Forward declaration of the view class. */
template<typename, typename...>
class basic_view;

/*! @brief Forward declaration of the group class. */
template<typename...>
class basic_group;

/*! @brief Forward declaration of the actor class. */
template <typename>
struct basic_actor;

/*! @brief Forward declaration of the prototype class. */
template<typename>
class basic_prototype;

/*! @brief Forward declaration of the snapshot class. */
template<typename>
class basic_snapshot;

/*! @brief Forward declaration of the snapshot loader class. */
template<typename>
class basic_snapshot_loader;

/*! @brief Forward declaration of the continuous loader class. */
template<typename>
class basic_continuous_loader;

/*! @brief Alias declaration for the most common use case. */
using entity = ENTT_ENTITY_TYPE;

/*! @brief Alias declaration for the most common use case. */
using registry = basic_registry<entity>;

/*! @brief Alias declaration for the most common use case. */
using actor = basic_actor<entity>;

/*! @brief Alias declaration for the most common use case. */
using prototype = basic_prototype<entity>;

/*! @brief Alias declaration for the most common use case. */
using snapshot = basic_snapshot<entity>;

/*! @brief Alias declaration for the most common use case. */
using snapshot_loader = basic_snapshot_loader<entity>;

/*! @brief Alias declaration for the most common use case. */
using continuous_loader = basic_continuous_loader<entity>;

/**
 * @brief Alias declaration for the most common use case.
 * @tparam Component Types of components iterated by the view.
 */
template<typename... Types>
using view = basic_view<entity, Types...>;

/**
 * @brief Alias declaration for the most common use case.
 * @tparam Types Types of components iterated by the group.
 */
template<typename... Types>
using group = basic_group<entity, Types...>;

}

#endif // ENTT_ENTITY_FWD_HPP
<commit_msg>added fwd decl for runtime view<commit_after>#ifndef ENTT_ENTITY_FWD_HPP
#define ENTT_ENTITY_FWD_HPP

#include "../config/config.h"

namespace entt {

/*! @brief Forward declaration of the registry class. */
template <typename>
class basic_registry;

/*! @brief Forward declaration of the view class. */
template<typename, typename...>
class basic_view;

/*! @brief Forward declaration of the runtime view class. */
template<typename>
class basic_runtime_view;

/*! @brief Forward declaration of the group class. */
template<typename...>
class basic_group;

/*! @brief Forward declaration of the actor class. */
template <typename>
struct basic_actor;

/*! @brief Forward declaration of the prototype class. */
template<typename>
class basic_prototype;

/*! @brief Forward declaration of the snapshot class. */
template<typename>
class basic_snapshot;

/*! @brief Forward declaration of the snapshot loader class. */
template<typename>
class basic_snapshot_loader;

/*! @brief Forward declaration of the continuous loader class. */
template<typename>
class basic_continuous_loader;

/*! @brief Alias declaration for the most common use case. */
using entity = ENTT_ENTITY_TYPE;

/*! @brief Alias declaration for the most common use case. */
using registry = basic_registry<entity>;

/*! @brief Alias declaration for the most common use case. */
using actor = basic_actor<entity>;

/*! @brief Alias declaration for the most common use case. */
using prototype = basic_prototype<entity>;

/*! @brief Alias declaration for the most common use case. */
using snapshot = basic_snapshot<entity>;

/*! @brief Alias declaration for the most common use case. */
using snapshot_loader = basic_snapshot_loader<entity>;

/*! @brief Alias declaration for the most common use case. */
using continuous_loader = basic_continuous_loader<entity>;

/**
 * @brief Alias declaration for the most common use case.
 * @tparam Component Types of components iterated by the view.
 */
template<typename... Types>
using view = basic_view<entity, Types...>;

/*! @brief Alias declaration for the most common use case. */
using runtime_view = basic_runtime_view<entity>;

/**
 * @brief Alias declaration for the most common use case.
 * @tparam Types Types of components iterated by the group.
 */
template<typename... Types>
using group = basic_group<entity, Types...>;

}

#endif // ENTT_ENTITY_FWD_HPP
<|endoftext|>