<commit_before>/*
 * Copyright (C) 2009 Toni Gundogdu.
 *
 * This file is part of cclive.
 *
 * cclive 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 3 of the License, or (at your option) any later
 * version.
 *
 * cclive 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, see <http://www.gnu.org/licenses/>.
 */

#ifdef HOST_W32
// A peculiar thing this one. If commented out or included *after* "config.h",
// mingw32-g++ returns: error: '::malloc' has not been declared
#include <cstdlib>
#endif

#include "config.h"

#include <iterator>
#include <sstream>
#include <climits>
#include <iomanip>
#include <string>
#include <vector>

#include "except.h"
#include "util.h"
#include "opts.h"
#include "curl.h"
#include "video.h"

VideoProperties::VideoProperties()
    : id(""),          link(""),      host(""),    domain(""),
      formats("flv"),  title(""),     length(0),   initial(0),
      contentType(""), suffix("flv"), filename(""),pageLink("")
{
}

void
VideoProperties::setId(const std::string& id) {
    this->id = id;
    Util::subStrReplace(this->id, "-", "_");
}

void
VideoProperties::setLink(std::string link) {
    this->link = curlmgr.unescape(link);
}

void
VideoProperties::setHost(const std::string& host) {
    this->host = host;
}

void
VideoProperties::setDomain(const std::string& domain) {
    this->domain = domain;
}

void
VideoProperties::setFormats(const std::string& formats) {
    this->formats = formats;
}

void
VideoProperties::setLength(const double length) {
    this->length = length;
}

void
VideoProperties::setPageLink(const std::string& link) {
    this->pageLink = link;
}

void
VideoProperties::setContentType(const std::string& contentType) {
    this->contentType = contentType;

    std::string::size_type pos = contentType.find("/");

    if (pos != std::string::npos) {
        suffix = contentType.substr(pos+1);
        // set to "flv" for these:
        if (suffix.find("octet") != std::string::npos
            || suffix.find("swf") != std::string::npos
            || suffix.find("plain") != std::string::npos)
        {
            suffix = "flv";
        }
        Util::subStrReplace(suffix, "x-", "");
    }
}

void
VideoProperties::setInitial(const double initial) {
    this->initial = initial;
}

void
VideoProperties::setTitle(const std::string& title) {
    this->title = title;
}

const std::string&
VideoProperties::getId() const {
    return id;
}

const std::string&
VideoProperties::getLink() const {
    return link;
}

const std::string&
VideoProperties::getHost() const {
    return host;
}

const std::string&
VideoProperties::getDomain() const {
    return domain;
}

const std::string&
VideoProperties::getFormats() const {
    return formats;
}

const std::string&
VideoProperties::getTitle() const {
    return title;
}

const double
VideoProperties::getLength() const {
    return length;
}

const std::string&
VideoProperties::getPageLink() const {
    return pageLink;
}

const double
VideoProperties::getInitial() const {
    return initial;
}

const std::string&
VideoProperties::getContentType() const {
    return contentType;
}

const std::string&
VideoProperties::getFilename() const {
    return filename;
}

static int video_num = 0;

void
VideoProperties::formatOutputFilename() {

    Options opts = optsmgr.getOptions();

    if (!opts.output_video_given) {
        std::stringstream b;

        if (opts.number_videos_given) {
            b << std::setw(4)
              << std::setfill('0')
              << ++video_num
              << "_";
        }

        customOutputFilenameFormatter(b);

        filename = b.str();

        for (register int i=1; i<INT_MAX; ++i) {
            initial = Util::fileExists(filename);

            if (initial == 0)
                break;
            else if (initial == length)
                throw NothingToDoException();
            else {
                if (opts.continue_given)
                    break;
            }
            std::stringstream tmp;
            tmp << b.str() << "." << i;
            filename = tmp.str();
        }
    }
    else {
        initial = Util::fileExists(opts.output_video_arg);
        if (initial == length)
            throw NothingToDoException();
        filename = opts.output_video_arg;
    }

    if (!opts.continue_given)
        initial = 0;
}

void
VideoProperties::customOutputFilenameFormatter(
    std::stringstream& b)
{
    Options opts    = optsmgr.getOptions();
    std::string fmt = opts.filename_format_arg;

    Util::subStrReplace(fmt, "%t", title);
    Util::subStrReplace(fmt, "%i", id);
    Util::subStrReplace(fmt, "%h", host);
    Util::subStrReplace(fmt, "%s", suffix);

    b << fmt;
}

VideoProperties::
    NothingToDoException::NothingToDoException()
    : RuntimeException(CCLIVE_NOTHINGTODO)
{
}
<commit_msg>Fix: empty video titles.<commit_after>/*
 * Copyright (C) 2009 Toni Gundogdu.
 *
 * This file is part of cclive.
 *
 * cclive 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 3 of the License, or (at your option) any later
 * version.
 *
 * cclive 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, see <http://www.gnu.org/licenses/>.
 */

#ifdef HOST_W32
// A peculiar thing this one. If commented out or included *after* "config.h",
// mingw32-g++ returns: error: '::malloc' has not been declared
#include <cstdlib>
#endif

#include "config.h"

#include <iterator>
#include <sstream>
#include <climits>
#include <iomanip>
#include <string>
#include <vector>

#include "except.h"
#include "util.h"
#include "opts.h"
#include "curl.h"
#include "video.h"

VideoProperties::VideoProperties()
    : id(""),          link(""),      host(""),    domain(""),
      formats("flv"),  title(""),     length(0),   initial(0),
      contentType(""), suffix("flv"), filename(""),pageLink("")
{
}

void
VideoProperties::setId(const std::string& id) {
    this->id = id;
    Util::subStrReplace(this->id, "-", "_");
}

void
VideoProperties::setLink(std::string link) {
    this->link = curlmgr.unescape(link);
}

void
VideoProperties::setHost(const std::string& host) {
    this->host = host;
}

void
VideoProperties::setDomain(const std::string& domain) {
    this->domain = domain;
}

void
VideoProperties::setFormats(const std::string& formats) {
    this->formats = formats;
}

void
VideoProperties::setLength(const double length) {
    this->length = length;
}

void
VideoProperties::setPageLink(const std::string& link) {
    this->pageLink = link;
}

void
VideoProperties::setContentType(const std::string& contentType) {
    this->contentType = contentType;

    std::string::size_type pos = contentType.find("/");

    if (pos != std::string::npos) {
        suffix = contentType.substr(pos+1);
        // set to "flv" for these:
        if (suffix.find("octet") != std::string::npos
            || suffix.find("swf") != std::string::npos
            || suffix.find("plain") != std::string::npos)
        {
            suffix = "flv";
        }
        Util::subStrReplace(suffix, "x-", "");
    }
}

void
VideoProperties::setInitial(const double initial) {
    this->initial = initial;
}

void
VideoProperties::setTitle(const std::string& title) {
    this->title = title;
}

const std::string&
VideoProperties::getId() const {
    return id;
}

const std::string&
VideoProperties::getLink() const {
    return link;
}

const std::string&
VideoProperties::getHost() const {
    return host;
}

const std::string&
VideoProperties::getDomain() const {
    return domain;
}

const std::string&
VideoProperties::getFormats() const {
    return formats;
}

const std::string&
VideoProperties::getTitle() const {
    return title;
}

const double
VideoProperties::getLength() const {
    return length;
}

const std::string&
VideoProperties::getPageLink() const {
    return pageLink;
}

const double
VideoProperties::getInitial() const {
    return initial;
}

const std::string&
VideoProperties::getContentType() const {
    return contentType;
}

const std::string&
VideoProperties::getFilename() const {
    return filename;
}

static int video_num = 0;

void
VideoProperties::formatOutputFilename() {

    Options opts = optsmgr.getOptions();

    if (!opts.output_video_given) {
        std::stringstream b;

        if (opts.number_videos_given) {
            b << std::setw(4)
              << std::setfill('0')
              << ++video_num
              << "_";
        }

        customOutputFilenameFormatter(b);

        filename = b.str();

        for (register int i=1; i<INT_MAX; ++i) {
            initial = Util::fileExists(filename);

            if (initial == 0)
                break;
            else if (initial == length)
                throw NothingToDoException();
            else {
                if (opts.continue_given)
                    break;
            }
            std::stringstream tmp;
            tmp << b.str() << "." << i;
            filename = tmp.str();
        }
    }
    else {
        initial = Util::fileExists(opts.output_video_arg);
        if (initial == length)
            throw NothingToDoException();
        filename = opts.output_video_arg;
    }

    if (!opts.continue_given)
        initial = 0;
}

void
VideoProperties::customOutputFilenameFormatter(
    std::stringstream& b)
{
    Options opts    = optsmgr.getOptions();
    std::string fmt = opts.filename_format_arg;

    Util::subStrReplace(fmt, "%t", title.empty() ? id : title);
    Util::subStrReplace(fmt, "%i", id);
    Util::subStrReplace(fmt, "%h", host);
    Util::subStrReplace(fmt, "%s", suffix);

    b << fmt;
}

VideoProperties::
    NothingToDoException::NothingToDoException()
    : RuntimeException(CCLIVE_NOTHINGTODO)
{
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012 Stanford University
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <stdio.h>

#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>

#include <string>
#include <set>
#include <sstream>
#include <iostream>
#include <algorithm>

#include <oriutil/debug.h>
#include <oriutil/oriutil.h>
#include <oriutil/orifile.h>
#include <oriutil/oricrypt.h>
#include <oriutil/scan.h>
#include <ori/repo.h>
#include <ori/largeblob.h>
#include <ori/tree.h>

using namespace std;

/********************************************************************
 *
 *
 * AttrMap
 *
 *
 ********************************************************************/

AttrMap::AttrMap()
{
}

bool AttrMap::has(const std::string &attrName) const
{
    return attrs.find(attrName) != attrs.end();
}

void AttrMap::setFromFile(const std::string &filename)
{
    struct stat sb;

    if (stat(filename.c_str(), &sb) < 0) {
	perror("AttrMap::setFromFile stat");
        fprintf(stderr, "(%s)\n", filename.c_str());
	PANIC();
    }

    struct passwd *upw = getpwuid(sb.st_uid);
    struct group *ggr = getgrgid(sb.st_gid);
    setAs<size_t>(ATTR_FILESIZE, sb.st_size);
    setAs<mode_t>(ATTR_PERMS, sb.st_mode & ~S_IFDIR & ~S_IFREG);
    attrs[ATTR_USERNAME] = upw->pw_name;
    attrs[ATTR_GROUPNAME] = ggr->gr_name;
    setAs<time_t>(ATTR_CTIME, sb.st_ctime);
    setAs<time_t>(ATTR_MTIME, sb.st_mtime);
}

void AttrMap::setCreation(mode_t perms)
{
    struct passwd *upw = getpwuid(geteuid());
    struct group *ggr = getgrgid(getegid());
    setAs<size_t>(ATTR_FILESIZE, 0);
    setAs<mode_t>(ATTR_PERMS, perms);
    attrs[ATTR_USERNAME] = upw->pw_name;
    attrs[ATTR_GROUPNAME] = ggr->gr_name;

    time_t currTime = time(NULL);
    setAs<time_t>(ATTR_CTIME, currTime);
    setAs<time_t>(ATTR_MTIME, currTime);
}

void AttrMap::mergeFrom(const AttrMap &other)
{
    for (auto const &it : other) {
        attrs[it.first] = it.second;
    }
}

/********************************************************************
 *
 *
 * TreeEntry
 *
 *
 ********************************************************************/

TreeEntry::TreeEntry()
{
    type = Null;
}

TreeEntry::TreeEntry(const ObjectHash &hash, const ObjectHash &lhash)
    : hash(hash), largeHash(lhash)
{
    if (lhash.isEmpty())
        type = Blob;
    else
        type = LargeBlob;
}

TreeEntry::~TreeEntry()
{
}

bool
TreeEntry::isTree()
{
    return type == Tree;
}

void
TreeEntry::extractToFile(const std::string &filename, Repo *src) const
{
    ASSERT(type != Null);
    Object::sp o(src->getObject(hash));
    if (type == Blob) {
        bytestream::ap bs(o->getPayloadStream());
        bs->copyToFile(filename);
    }
    else if (type == LargeBlob) {
        ::LargeBlob lb(src);
        lb.fromBlob(o->getPayload());
        lb.extractFile(filename);
    }
    else {
        NOT_IMPLEMENTED(false);
    }
}

bool
TreeEntry::hasBasicAttrs()
{
    const char *names[] = {ATTR_FILESIZE, ATTR_PERMS, ATTR_USERNAME,
        ATTR_GROUPNAME, ATTR_CTIME, ATTR_MTIME};
    for (size_t i = 0; i < sizeof(names) / sizeof(const char *); i++) {
        //LOG("Checking attr %s", names[i]);
        if (attrs.attrs.find(names[i]) == attrs.attrs.end())
        {
            WARNING("Attribute '%s' does not exist", names[i]);
            return false;
        }
    }
    return true;
}

void
TreeEntry::print() const
{
    AttrMap::const_iterator it;

    cout << "  Hash: " << hash.hex() << endl;
    if (type == TreeEntry::LargeBlob)
        cout << "  Large Hash: " << largeHash.hex() << endl;

    cout << "  Size: " << attrs.getAs<size_t>(ATTR_FILESIZE) << endl;
    cout << "  User: " << attrs.getAsStr(ATTR_USERNAME) << endl;
    cout << "  Group: " << attrs.getAsStr(ATTR_GROUPNAME) << endl;
    // perms and link
    cout << "  Created: " << attrs.getAs<time_t>(ATTR_CTIME) << endl;
    cout << "  Modified: " << attrs.getAs<time_t>(ATTR_MTIME) << endl;
}

/********************************************************************
 *
 *
 * Tree
 *
 *
 ********************************************************************/

Tree::Tree()
{
}

Tree::~Tree()
{
}

const string
Tree::getBlob() const
{
    strwstream ss;
    ss.enableTypes();
    size_t size = tree.size();
    ss.writeUInt64(size);

    for (auto const &it : tree) {
        const TreeEntry &te = it.second;
        if (te.type == TreeEntry::Tree) {
            ss.write("tree", 4);
        } else if (te.type == TreeEntry::Blob) {
            ss.write("blob", 4);
        } else if (te.type == TreeEntry::LargeBlob) {
            ss.write("lgbl", 4);
        } else {
            PANIC();
        }

        ss.writeHash(te.hash);
        if (te.type == TreeEntry::LargeBlob)
            ss.writeHash(te.largeHash);
        ss.writePStr(it.first);

        size_t asize = te.attrs.attrs.size();
        ss.writeUInt32(asize);
        for (auto const &ait : te.attrs.attrs) {
            ss.writePStr(ait.first);
            ss.writePStr(ait.second);
        }
    }

    return ss.str();
}

void
Tree::fromBlob(const string &blob)
{
    strstream ss(blob);
    ss.enableTypes();
    size_t num_entries = ss.readUInt64();

    for (size_t i = 0; i < num_entries; i++) {
        TreeEntry entry;
        char type[5] = {'\0'};
        ss.readExact((uint8_t*)type, 4);
        if (strcmp(type, "tree") == 0) {
            entry.type = TreeEntry::Tree;
        }
        else if (strcmp(type, "blob") == 0) {
            entry.type = TreeEntry::Blob;
        }
        else if (strcmp(type, "lgbl") == 0) {
            entry.type = TreeEntry::LargeBlob;
        }
        else {
            PANIC();
        }

        ss.readHash(entry.hash);
        if (entry.type == TreeEntry::LargeBlob) {
            ss.readHash(entry.largeHash);
        }
        string path;
        int status = ss.readPStr(path);
        ASSERT(status > 0);

        size_t num_attrs = ss.readUInt32();
        for (size_t i_a = 0; i_a < num_attrs; i_a++) {
            string attrName, attrValue;

            status = ss.readPStr(attrName);
            ASSERT(status > 0);
            status = ss.readPStr(attrValue);
            ASSERT(status > 0);

            entry.attrs.attrs[attrName] = attrValue;
        }

        tree[path] = entry;
    }
}

void
_recFlatten(
        const std::string &prefix,
        const Tree *t,
        Tree::Flat *rval,
        Repo *r
        )
{
    for (auto const &it : t->tree) {
        const TreeEntry &te = it.second;
        rval->insert(make_pair(prefix + it.first, te));
        if (te.type == TreeEntry::Tree) {
            // Recurse further
            Tree subtree = r->getTree(te.hash);
            _recFlatten(prefix + it.first + "/",
                    &subtree, rval, r);
        }
    }
}

/*
 * Constructs a flat tree given the repository that this tree was taken from.
 */
Tree::Flat
Tree::flattened(Repo *r) const
{
    Tree::Flat rval;
    _recFlatten("/", this, &rval, r);
    return rval;
}

size_t _num_path_components(const std::string &path)
{
    if (path.size() == 0) return 0;
    size_t cnt = 0;
    for (size_t i = 0; i < path.size(); i++) {
        if (path[i] == '/')
            cnt++;
    }
    return 1 + cnt;
}

bool _tree_gt(const std::string &t1, const std::string &t2)
{
    return _num_path_components(t1) > _num_path_components(t2);
}

/*
 * Commits a flat tree into the repository 'r'. This function returns a tree
 * object for the root tree that was committed.
 */
Tree
Tree::unflatten(const Flat &flat, Repo *r)
{
    map<string, Tree> trees;
    for (auto const &it : flat) {
        const TreeEntry &te = it.second;
        if (te.type == TreeEntry::Tree) {
            if (trees.find(it.first) == trees.end()) {
                trees[it.first] = Tree();
            }
        }
        else if (te.type == TreeEntry::Blob ||
                te.type == TreeEntry::LargeBlob) {
            string treename = OriFile_Dirname(it.first);
            if (trees.find(treename) == trees.end()) {
                trees[treename] = Tree();
            }
            string basename = OriFile_Basename(it.first);
            trees[treename].tree[basename] = te;
        }
        else {
            ASSERT(false && "TreeEntry is type Null");
        }
    }

    // Get the tree hashes, update parents, add to Repo
    vector<string> tree_names;
    for (auto const &it : trees) {
        tree_names.push_back(it.first);
    }
    // Update leaf trees (no child directories) first
    std::sort(tree_names.begin(), tree_names.end(), _tree_gt);

    for (size_t i = 0; i < tree_names.size(); i++) {
        const string &tn = tree_names[i];
        if (tn.size() == 0) continue;
        string blob = trees[tn].getBlob();
        ObjectHash hash = OriCrypt_HashString(blob);

        // Add to Repo
        r->addObject(ObjectInfo::Tree, hash, blob);

        // Add to parent
        TreeEntry te = (*flat.find(tree_names[i])).second;
        te.hash = hash;
        te.type = TreeEntry::Tree;
        ASSERT(te.hasBasicAttrs());

        string parent = OriFile_Dirname(tn);
        trees[parent].tree[OriFile_Basename(tn)] = te;
    }

    r->addBlob(ObjectInfo::Tree, trees[""].getBlob());

    return trees[""];
}

ObjectHash
Tree::hash() const
{
    return OriCrypt_HashString(getBlob());
}

void
Tree::print() const
{
    map<string, TreeEntry>::const_iterator it;

    for (auto &it : tree)
    {
	cout << "Path: " << it.first << endl;
	switch (it.second.type)
	{
	    case TreeEntry::Null:
		cout << "  Type: Null" << endl;
		break;
	    case TreeEntry::Blob:
		cout << "  Type: Blob" << endl;
		break;
	    case TreeEntry::LargeBlob:
		cout << "  Type: LargeBlob" << endl;
		break;
	    case TreeEntry::Tree:
		cout << "  Type: Tree" << endl;
		break;
	    default:
		NOT_IMPLEMENTED(false);
		break;
	}

	it.second.print();
    }
}

<commit_msg>Fix oridb rebuildindex bug: check for empty tree in fromBlob<commit_after>/*
 * Copyright (c) 2012 Stanford University
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <stdio.h>

#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>

#include <string>
#include <set>
#include <sstream>
#include <iostream>
#include <algorithm>

#include <oriutil/debug.h>
#include <oriutil/oriutil.h>
#include <oriutil/orifile.h>
#include <oriutil/oricrypt.h>
#include <oriutil/scan.h>
#include <ori/repo.h>
#include <ori/largeblob.h>
#include <ori/tree.h>

using namespace std;

/********************************************************************
 *
 *
 * AttrMap
 *
 *
 ********************************************************************/

AttrMap::AttrMap()
{
}

bool AttrMap::has(const std::string &attrName) const
{
    return attrs.find(attrName) != attrs.end();
}

void AttrMap::setFromFile(const std::string &filename)
{
    struct stat sb;

    if (stat(filename.c_str(), &sb) < 0) {
	perror("AttrMap::setFromFile stat");
        fprintf(stderr, "(%s)\n", filename.c_str());
	PANIC();
    }

    struct passwd *upw = getpwuid(sb.st_uid);
    struct group *ggr = getgrgid(sb.st_gid);
    setAs<size_t>(ATTR_FILESIZE, sb.st_size);
    setAs<mode_t>(ATTR_PERMS, sb.st_mode & ~S_IFDIR & ~S_IFREG);
    attrs[ATTR_USERNAME] = upw->pw_name;
    attrs[ATTR_GROUPNAME] = ggr->gr_name;
    setAs<time_t>(ATTR_CTIME, sb.st_ctime);
    setAs<time_t>(ATTR_MTIME, sb.st_mtime);
}

void AttrMap::setCreation(mode_t perms)
{
    struct passwd *upw = getpwuid(geteuid());
    struct group *ggr = getgrgid(getegid());
    setAs<size_t>(ATTR_FILESIZE, 0);
    setAs<mode_t>(ATTR_PERMS, perms);
    attrs[ATTR_USERNAME] = upw->pw_name;
    attrs[ATTR_GROUPNAME] = ggr->gr_name;

    time_t currTime = time(NULL);
    setAs<time_t>(ATTR_CTIME, currTime);
    setAs<time_t>(ATTR_MTIME, currTime);
}

void AttrMap::mergeFrom(const AttrMap &other)
{
    for (auto const &it : other) {
        attrs[it.first] = it.second;
    }
}

/********************************************************************
 *
 *
 * TreeEntry
 *
 *
 ********************************************************************/

TreeEntry::TreeEntry()
{
    type = Null;
}

TreeEntry::TreeEntry(const ObjectHash &hash, const ObjectHash &lhash)
    : hash(hash), largeHash(lhash)
{
    if (lhash.isEmpty())
        type = Blob;
    else
        type = LargeBlob;
}

TreeEntry::~TreeEntry()
{
}

bool
TreeEntry::isTree()
{
    return type == Tree;
}

void
TreeEntry::extractToFile(const std::string &filename, Repo *src) const
{
    ASSERT(type != Null);
    Object::sp o(src->getObject(hash));
    if (type == Blob) {
        bytestream::ap bs(o->getPayloadStream());
        bs->copyToFile(filename);
    }
    else if (type == LargeBlob) {
        ::LargeBlob lb(src);
        lb.fromBlob(o->getPayload());
        lb.extractFile(filename);
    }
    else {
        NOT_IMPLEMENTED(false);
    }
}

bool
TreeEntry::hasBasicAttrs()
{
    const char *names[] = {ATTR_FILESIZE, ATTR_PERMS, ATTR_USERNAME,
        ATTR_GROUPNAME, ATTR_CTIME, ATTR_MTIME};
    for (size_t i = 0; i < sizeof(names) / sizeof(const char *); i++) {
        //LOG("Checking attr %s", names[i]);
        if (attrs.attrs.find(names[i]) == attrs.attrs.end())
        {
            WARNING("Attribute '%s' does not exist", names[i]);
            return false;
        }
    }
    return true;
}

void
TreeEntry::print() const
{
    AttrMap::const_iterator it;

    cout << "  Hash: " << hash.hex() << endl;
    if (type == TreeEntry::LargeBlob)
        cout << "  Large Hash: " << largeHash.hex() << endl;

    cout << "  Size: " << attrs.getAs<size_t>(ATTR_FILESIZE) << endl;
    cout << "  User: " << attrs.getAsStr(ATTR_USERNAME) << endl;
    cout << "  Group: " << attrs.getAsStr(ATTR_GROUPNAME) << endl;
    // perms and link
    cout << "  Created: " << attrs.getAs<time_t>(ATTR_CTIME) << endl;
    cout << "  Modified: " << attrs.getAs<time_t>(ATTR_MTIME) << endl;
}

/********************************************************************
 *
 *
 * Tree
 *
 *
 ********************************************************************/

Tree::Tree()
{
}

Tree::~Tree()
{
}

const string
Tree::getBlob() const
{
    strwstream ss;
    ss.enableTypes();
    size_t size = tree.size();
    ss.writeUInt64(size);

    for (auto const &it : tree) {
        const TreeEntry &te = it.second;
        if (te.type == TreeEntry::Tree) {
            ss.write("tree", 4);
        } else if (te.type == TreeEntry::Blob) {
            ss.write("blob", 4);
        } else if (te.type == TreeEntry::LargeBlob) {
            ss.write("lgbl", 4);
        } else {
            PANIC();
        }

        ss.writeHash(te.hash);
        if (te.type == TreeEntry::LargeBlob)
            ss.writeHash(te.largeHash);
        ss.writePStr(it.first);

        size_t asize = te.attrs.attrs.size();
        ss.writeUInt32(asize);
        for (auto const &ait : te.attrs.attrs) {
            ss.writePStr(ait.first);
            ss.writePStr(ait.second);
        }
    }

    return ss.str();
}

void
Tree::fromBlob(const string &blob)
{
    strstream ss(blob);
    ss.enableTypes();
    size_t num_entries = (blob == "") ? 0 : ss.readUInt64();

    for (size_t i = 0; i < num_entries; i++) {
        TreeEntry entry;
        char type[5] = {'\0'};
        ss.readExact((uint8_t*)type, 4);
        if (strcmp(type, "tree") == 0) {
            entry.type = TreeEntry::Tree;
        }
        else if (strcmp(type, "blob") == 0) {
            entry.type = TreeEntry::Blob;
        }
        else if (strcmp(type, "lgbl") == 0) {
            entry.type = TreeEntry::LargeBlob;
        }
        else {
            PANIC();
        }

        ss.readHash(entry.hash);
        if (entry.type == TreeEntry::LargeBlob) {
            ss.readHash(entry.largeHash);
        }
        string path;
        int status = ss.readPStr(path);
        ASSERT(status > 0);

        size_t num_attrs = ss.readUInt32();
        for (size_t i_a = 0; i_a < num_attrs; i_a++) {
            string attrName, attrValue;

            status = ss.readPStr(attrName);
            ASSERT(status > 0);
            status = ss.readPStr(attrValue);
            ASSERT(status > 0);

            entry.attrs.attrs[attrName] = attrValue;
        }

        tree[path] = entry;
    }
}

void
_recFlatten(
        const std::string &prefix,
        const Tree *t,
        Tree::Flat *rval,
        Repo *r
        )
{
    for (auto const &it : t->tree) {
        const TreeEntry &te = it.second;
        rval->insert(make_pair(prefix + it.first, te));
        if (te.type == TreeEntry::Tree) {
            // Recurse further
            Tree subtree = r->getTree(te.hash);
            _recFlatten(prefix + it.first + "/",
                    &subtree, rval, r);
        }
    }
}

/*
 * Constructs a flat tree given the repository that this tree was taken from.
 */
Tree::Flat
Tree::flattened(Repo *r) const
{
    Tree::Flat rval;
    _recFlatten("/", this, &rval, r);
    return rval;
}

size_t _num_path_components(const std::string &path)
{
    if (path.size() == 0) return 0;
    size_t cnt = 0;
    for (size_t i = 0; i < path.size(); i++) {
        if (path[i] == '/')
            cnt++;
    }
    return 1 + cnt;
}

bool _tree_gt(const std::string &t1, const std::string &t2)
{
    return _num_path_components(t1) > _num_path_components(t2);
}

/*
 * Commits a flat tree into the repository 'r'. This function returns a tree
 * object for the root tree that was committed.
 */
Tree
Tree::unflatten(const Flat &flat, Repo *r)
{
    map<string, Tree> trees;
    for (auto const &it : flat) {
        const TreeEntry &te = it.second;
        if (te.type == TreeEntry::Tree) {
            if (trees.find(it.first) == trees.end()) {
                trees[it.first] = Tree();
            }
        }
        else if (te.type == TreeEntry::Blob ||
                te.type == TreeEntry::LargeBlob) {
            string treename = OriFile_Dirname(it.first);
            if (trees.find(treename) == trees.end()) {
                trees[treename] = Tree();
            }
            string basename = OriFile_Basename(it.first);
            trees[treename].tree[basename] = te;
        }
        else {
            ASSERT(false && "TreeEntry is type Null");
        }
    }

    // Get the tree hashes, update parents, add to Repo
    vector<string> tree_names;
    for (auto const &it : trees) {
        tree_names.push_back(it.first);
    }
    // Update leaf trees (no child directories) first
    std::sort(tree_names.begin(), tree_names.end(), _tree_gt);

    for (size_t i = 0; i < tree_names.size(); i++) {
        const string &tn = tree_names[i];
        if (tn.size() == 0) continue;
        string blob = trees[tn].getBlob();
        ObjectHash hash = OriCrypt_HashString(blob);

        // Add to Repo
        r->addObject(ObjectInfo::Tree, hash, blob);

        // Add to parent
        TreeEntry te = (*flat.find(tree_names[i])).second;
        te.hash = hash;
        te.type = TreeEntry::Tree;
        ASSERT(te.hasBasicAttrs());

        string parent = OriFile_Dirname(tn);
        trees[parent].tree[OriFile_Basename(tn)] = te;
    }

    r->addBlob(ObjectInfo::Tree, trees[""].getBlob());

    return trees[""];
}

ObjectHash
Tree::hash() const
{
    return OriCrypt_HashString(getBlob());
}

void
Tree::print() const
{
    map<string, TreeEntry>::const_iterator it;

    for (auto &it : tree)
    {
	cout << "Path: " << it.first << endl;
	switch (it.second.type)
	{
	    case TreeEntry::Null:
		cout << "  Type: Null" << endl;
		break;
	    case TreeEntry::Blob:
		cout << "  Type: Blob" << endl;
		break;
	    case TreeEntry::LargeBlob:
		cout << "  Type: LargeBlob" << endl;
		break;
	    case TreeEntry::Tree:
		cout << "  Type: Tree" << endl;
		break;
	    default:
		NOT_IMPLEMENTED(false);
		break;
	}

	it.second.print();
    }
}

<|endoftext|>


<commit_before>/*
 * cclive Copyright (C) 2009 Toni Gundogdu. This file is part of cclive.
 *
 * cclive 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 3 of the License, or (at your option) any later
 * version.
 *
 * cclive 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, see <http://www.gnu.org/licenses/>.
 */

#include <string>
#include <vector>
#include <sstream>
#include <iterator>
#include <climits>

#include "util.h"
#include "singleton.h"
#include "cmdline.h"
#include "opts.h"
#include "except.h"
#include "curl.h"
#include "video.h"

VideoProperties::VideoProperties()
    : id(""),         link(""),     host(""),    domain(""),
      title(""),      length(0),    initial(0),  contentType(""),
      suffix("flv"),  filename("")

{
}

void
VideoProperties::setId(const std::string& id) {
    this->id = id;
}

void
VideoProperties::setLink(std::string link) {
    this->link = curlmgr.unescape(link);
}

void
VideoProperties::setHost(const std::string& host) {
    this->host = host;
}

void
VideoProperties::setDomain(const std::string& domain) {
    this->domain = domain;
}

void
VideoProperties::setLength(const double length) {
    this->length = length;
}

void
VideoProperties::setContentType(const std::string& contentType) {
    this->contentType = contentType;

    std::string::size_type pos = contentType.find("/");

    if (pos != std::string::npos) {
        suffix = contentType.substr(pos+1);
        // set to "flv" for these:
        if (suffix.find("octet") != std::string::npos
            || suffix.find("x-flv") != std::string::npos
            || suffix.find("plain") != std::string::npos)
        {
            suffix = "flv";
        }
    }

    // We have all needed info now.
    formatOutputFilename();
}

void
VideoProperties::setInitial(const double initial) {
    this->initial = initial;
}

void
VideoProperties::setTitle(const std::string& title) {
    this->title = title;
}

const std::string&
VideoProperties::getId() const {
    return id;
}

const std::string&
VideoProperties::getLink() const {
    return link;
}

const std::string&
VideoProperties::getHost() const {
    return host;
}

const std::string&
VideoProperties::getDomain() const {
    return domain;
}

const double
VideoProperties::getLength() const {
    return length;
}

const double
VideoProperties::getInitial() const {
    return initial;
}

const std::string&
VideoProperties::getContentType() const {
    return contentType;
}

const std::string&
VideoProperties::getFilename() const {
    return filename;
}

static int video_num;

void
VideoProperties::formatOutputFilename() {
    Util::subStrReplace(id, "-", "_");

    Options opts = optsmgr.getOptions();

    if (!opts.output_video_given) {
        std::stringstream b;

        if (opts.number_videos_given)
            b << ++video_num << "_";

        if (opts.title_given && title.length() > 0)
            b << title;
        else
            b << host << "_" << id;

        b << "." << suffix;
        filename = b.str();

        for (register int i=1; i<INT_MAX; ++i) {
            initial = Util::fileExists(filename);

            if (initial == 0)
                break;
            else if (initial == length)
                throw NothingToDoException();
            else {
                if (opts.continue_given)
                    break;
            }
            std::stringstream tmp;
            tmp << b.str() << "." << i;
            filename = tmp.str();
        }
    }
    else {
        initial = Util::fileExists(opts.output_video_arg);
        if (initial == length)
            throw NothingToDoException();
        filename = opts.output_video_arg;
    }

    if (!opts.continue_given)
        initial = 0;
}

VideoProperties::
    NothingToDoException::NothingToDoException()
    : RuntimeException()
{
}
<commit_msg>Fix --number-videos: add zero-padding.<commit_after>/*
 * cclive Copyright (C) 2009 Toni Gundogdu. This file is part of cclive.
 *
 * cclive 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 3 of the License, or (at your option) any later
 * version.
 *
 * cclive 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, see <http://www.gnu.org/licenses/>.
 */

#include <string>
#include <vector>
#include <sstream>
#include <iterator>
#include <climits>
#include <iomanip>

#include "util.h"
#include "singleton.h"
#include "cmdline.h"
#include "opts.h"
#include "except.h"
#include "curl.h"
#include "video.h"

VideoProperties::VideoProperties()
    : id(""),         link(""),     host(""),    domain(""),
      title(""),      length(0),    initial(0),  contentType(""),
      suffix("flv"),  filename("")

{
}

void
VideoProperties::setId(const std::string& id) {
    this->id = id;
}

void
VideoProperties::setLink(std::string link) {
    this->link = curlmgr.unescape(link);
}

void
VideoProperties::setHost(const std::string& host) {
    this->host = host;
}

void
VideoProperties::setDomain(const std::string& domain) {
    this->domain = domain;
}

void
VideoProperties::setLength(const double length) {
    this->length = length;
}

void
VideoProperties::setContentType(const std::string& contentType) {
    this->contentType = contentType;

    std::string::size_type pos = contentType.find("/");

    if (pos != std::string::npos) {
        suffix = contentType.substr(pos+1);
        // set to "flv" for these:
        if (suffix.find("octet") != std::string::npos
            || suffix.find("x-flv") != std::string::npos
            || suffix.find("plain") != std::string::npos)
        {
            suffix = "flv";
        }
    }

    // We have all needed info now.
    formatOutputFilename();
}

void
VideoProperties::setInitial(const double initial) {
    this->initial = initial;
}

void
VideoProperties::setTitle(const std::string& title) {
    this->title = title;
}

const std::string&
VideoProperties::getId() const {
    return id;
}

const std::string&
VideoProperties::getLink() const {
    return link;
}

const std::string&
VideoProperties::getHost() const {
    return host;
}

const std::string&
VideoProperties::getDomain() const {
    return domain;
}

const double
VideoProperties::getLength() const {
    return length;
}

const double
VideoProperties::getInitial() const {
    return initial;
}

const std::string&
VideoProperties::getContentType() const {
    return contentType;
}

const std::string&
VideoProperties::getFilename() const {
    return filename;
}

static int video_num;

void
VideoProperties::formatOutputFilename() {
    Util::subStrReplace(id, "-", "_");

    Options opts = optsmgr.getOptions();

    if (!opts.output_video_given) {
        std::stringstream b;

        if (opts.number_videos_given) {
            b << std::setw(4)
              << std::setfill('0')
              << ++video_num
              << "_";
        }

        if (opts.title_given && title.length() > 0)
            b << title;
        else
            b << host << "_" << id;

        b << "." << suffix;
        filename = b.str();

        for (register int i=1; i<INT_MAX; ++i) {
            initial = Util::fileExists(filename);

            if (initial == 0)
                break;
            else if (initial == length)
                throw NothingToDoException();
            else {
                if (opts.continue_given)
                    break;
            }
            std::stringstream tmp;
            tmp << b.str() << "." << i;
            filename = tmp.str();
        }
    }
    else {
        initial = Util::fileExists(opts.output_video_arg);
        if (initial == length)
            throw NothingToDoException();
        filename = opts.output_video_arg;
    }

    if (!opts.continue_given)
        initial = 0;
}

VideoProperties::
    NothingToDoException::NothingToDoException()
    : RuntimeException()
{
}
<|endoftext|>


<commit_before>
#include <iostream>
#include <fstream>
#include "mdataTools.hpp"
#include "mordorBinaryReader.hpp"
#include "readMData5.hpp"
#include "assert.h"

using namespace std;

struct header{
  char* version;
  WORD numMonsters;
};

struct monster{
  char* name;
  WORD attackRating;
  WORD defenceRating;
  WORD id;
  WORD hitPoints;
  WORD groupSize;
  WORD portaitID;
  WORD u8;
  WORD appearOnLevel;
  WORD fireResistance;
  WORD coldResistance;
  WORD electricalResistance;
  WORD mindResistance;
  WORD diseaseResistance;
  WORD poisonResistance;
  WORD magicResistance;
  WORD stoneResistance;
  WORD paralysisResistance;
  WORD drainResistance;
  WORD acidResistance;
  WORD u21, u22, u23, u24, u25, u26, u27;
  WORD encounterChance;
  WORD nothingChance;
  WORD boxChance;
  WORD chestChance;
  WORD u32, u33, u34, u35, u36, u37, u38;
  WORD strength;
  WORD intelligence;
  WORD wisdom;
  WORD constitution;
  WORD dexterity;
  WORD u45, u46, u47, u48, u49, u50, u51, u52;
};

void printHeader(const header *ret){
  cout << ret->version << "\tNum Monsters: "
       << ret->numMonsters << endl;
}

header readHeader(ifstream *mdata){
  header ret;

  ret.version = readVBString(mdata);
  ret.numMonsters = readWord(mdata);

  printHeader(&ret);
  return ret;
}

void printMonster(monster *m){
  cout << m->name << endl
       << "Attack Rating: " << m->attackRating << endl
       << "defenceRating" << m->defenceRating << endl
       << "ID" << m->id << endl
       << "HP" << m->hitPoints << endl
       << "groupSize" << m->groupSize << endl
       << "portraitID" << m->portaitID << endl
       << "u8" << m->u8 << endl
       << "appearOnLevel" << m->appearOnLevel << endl
       << "fireResistance" << m->fireResistance << endl
       << "coldResistance" << m->coldResistance << endl
       << "electricalResistance" << m->electricalResistance << endl
       << "mindResistance" << m->mindResistance << endl
       << "diseaseResistance" << m->diseaseResistance << endl
       << "poisonResistance" << m->poisonResistance << endl
       << "magicResistance" << m->magicResistance << endl
       << "stoneResistance" << m->stoneResistance << endl
       << "paralyisResistance" << m->paralysisResistance << endl
       << "drainResistance" << m->drainResistance << endl
       << "acidResistance" << m->acidResistance << endl
       << "u21" << m->u21 << endl
       << "u22" << m->u22 << endl
       << "u23" << m->u23 << endl
       << "u24" << m->u24 << endl
       << "u25" << m->u25 << endl
       << "u26" << m->u26 << endl
       << "u27" << m->u27 << endl
       << "encounterChance" << m->encounterChance << endl
       << "nothingChance" << m->nothingChance << endl
       << "boxChance" << m->boxChance << endl
       << "chestChance" << m->chestChance << endl
       << "u32" << m->u32 << endl
       << "u33" << m->u33 << endl
       << "u34" << m->u34 << endl
       << "u35" << m->u35 << endl
       << "u36" << m->u36 << endl
       << "u37" << m->u37 << endl
       << "u38" << m->u38 << endl
       << "strength" << m->strength << endl
       << "intelligence" << m->intelligence << endl
       << "wisdom" << m->wisdom << endl
       << "constitution" << m->constitution << endl
       << "dexterity" << m->dexterity << endl
       << "u45" << m->u45 << endl
       << "u46" << m->u46 << endl
       << "u47" << m->u47 << endl
       << "u48" << m->u48 << endl
       << "u49" << m->u49 << endl
       << "u50" << m->u50 << endl
       << "u51" << m->u51 << endl
       << "u52" << m->u52 << endl;
}

monster readMonster(ifstream *mdata){
  monster ret;

  printMonster(&ret);
  return ret;
}

int main(int argc, char** argv){
  char* datAbsolutePath;

  if(argc != 2){
    cerr << "Expected exactly one argument -- the absolute path to the MDATA5.MDR" << endl;
    return 1;
  }else{
    datAbsolutePath = argv[1];
  }

  if (not possiblyValidFile(datAbsolutePath, MDATA5)){
    cerr << datAbsolutePath << " doesn't appear to be a valid MDATA5.MDR" << endl;
    return 1;
  }

  return 0;
}
<commit_msg>first hack at read monster<commit_after>
#include <iostream>
#include <fstream>
#include "mdataTools.hpp"
#include "mordorBinaryReader.hpp"
#include "readMData5.hpp"
#include "assert.h"

using namespace std;

struct header{
  char* version;
  WORD numMonsters;
};

struct monster{
  char* name;
  WORD attackRating;
  WORD defenceRating;
  WORD id;
  WORD hitPoints;
  WORD groupSize;
  WORD portaitID;
  WORD u8;
  WORD appearOnLevel;
  WORD fireResistance;
  WORD coldResistance;
  WORD electricalResistance;
  WORD mindResistance;
  WORD diseaseResistance;
  WORD poisonResistance;
  WORD magicResistance;
  WORD stoneResistance;
  WORD paralysisResistance;
  WORD drainResistance;
  WORD acidResistance;
  WORD u21, u22, u23, u24, u25, u26, u27;
  WORD encounterChance;
  WORD nothingChance;
  WORD boxChance;
  WORD chestChance;
  WORD u32, u33, u34, u35, u36, u37, u38;
  WORD strength;
  WORD intelligence;
  WORD wisdom;
  WORD constitution;
  WORD dexterity;
  WORD u45, u46, u47, u48, u49, u50, u51, u52;
};

void printHeader(const header *ret){
  cout << ret->version << "\tNum Monsters: "
       << ret->numMonsters << endl;
}

header readHeader(ifstream *mdata){
  header ret;

  ret.version = readVBString(mdata);
  ret.numMonsters = readWord(mdata);

  printHeader(&ret);
  return ret;
}

void printMonster(monster *m){
  cout << m->name << endl
       << "Attack Rating: " << m->attackRating << endl
       << "defenceRating" << m->defenceRating << endl
       << "ID" << m->id << endl
       << "HP" << m->hitPoints << endl
       << "groupSize" << m->groupSize << endl
       << "portraitID" << m->portaitID << endl
       << "u8" << m->u8 << endl
       << "appearOnLevel" << m->appearOnLevel << endl
       << "fireResistance" << m->fireResistance << endl
       << "coldResistance" << m->coldResistance << endl
       << "electricalResistance" << m->electricalResistance << endl
       << "mindResistance" << m->mindResistance << endl
       << "diseaseResistance" << m->diseaseResistance << endl
       << "poisonResistance" << m->poisonResistance << endl
       << "magicResistance" << m->magicResistance << endl
       << "stoneResistance" << m->stoneResistance << endl
       << "paralyisResistance" << m->paralysisResistance << endl
       << "drainResistance" << m->drainResistance << endl
       << "acidResistance" << m->acidResistance << endl
       << "u21" << m->u21 << endl
       << "u22" << m->u22 << endl
       << "u23" << m->u23 << endl
       << "u24" << m->u24 << endl
       << "u25" << m->u25 << endl
       << "u26" << m->u26 << endl
       << "u27" << m->u27 << endl
       << "encounterChance" << m->encounterChance << endl
       << "nothingChance" << m->nothingChance << endl
       << "boxChance" << m->boxChance << endl
       << "chestChance" << m->chestChance << endl
       << "u32" << m->u32 << endl
       << "u33" << m->u33 << endl
       << "u34" << m->u34 << endl
       << "u35" << m->u35 << endl
       << "u36" << m->u36 << endl
       << "u37" << m->u37 << endl
       << "u38" << m->u38 << endl
       << "strength" << m->strength << endl
       << "intelligence" << m->intelligence << endl
       << "wisdom" << m->wisdom << endl
       << "constitution" << m->constitution << endl
       << "dexterity" << m->dexterity << endl
       << "u45" << m->u45 << endl
       << "u46" << m->u46 << endl
       << "u47" << m->u47 << endl
       << "u48" << m->u48 << endl
       << "u49" << m->u49 << endl
       << "u50" << m->u50 << endl
       << "u51" << m->u51 << endl
       << "u52" << m->u52 << endl;
}

monster readMonster(ifstream *mdata){
  monster ret;
  ret.name = readVBString(mdata);
  ret.attackRating = readWord(mdata);
  ret.defenceRating = readWord(mdata);
  ret.id = readWord(mdata);
  ret.hitPoints = readWord(mdata);
  ret.groupSize = readWord(mdata);
  ret.portaitID = readWord(mdata);
  ret.u8 = readWord(mdata);
  ret.appearOnLevel = readWord(mdata);
  ret.fireResistance = readWord(mdata);
  ret.coldResistance = readWord(mdata);
  ret.electricalResistance = readWord(mdata);
  ret.mindResistance = readWord(mdata);
  ret.diseaseResistance = readWord(mdata);
  ret.poisonResistance = readWord(mdata);
  ret.magicResistance = readWord(mdata);
  ret.stoneResistance = readWord(mdata);
  ret.paralysisResistance = readWord(mdata);
  ret.drainResistance = readWord(mdata);
  ret.acidResistance = readWord(mdata);
  ret.u21 = readWord(mdata);
  ret.u22 = readWord(mdata);
  ret.u23 = readWord(mdata);
  ret.u24 = readWord(mdata);
  ret.u25 = readWord(mdata);
  ret.u26 = readWord(mdata);
  ret.u27 = readWord(mdata);
  ret.encounterChance = readWord(mdata);
  ret.nothingChance = readWord(mdata);
  ret.boxChance = readWord(mdata);
  ret.chestChance = readWord(mdata);
  ret.u32 = readWord(mdata);
  ret.u33 = readWord(mdata);
  ret.u34 = readWord(mdata);
  ret.u35 = readWord(mdata);
  ret.u36 = readWord(mdata);
  ret.u37 = readWord(mdata);
  ret.u38 = readWord(mdata);
  ret.strength = readWord(mdata);
  ret.intelligence = readWord(mdata);
  ret.wisdom = readWord(mdata);
  ret.constitution = readWord(mdata);
  ret.dexterity = readWord(mdata);
  ret.u45 = readWord(mdata);
  ret.u46 = readWord(mdata);
  ret.u47 = readWord(mdata);
  ret.u48 = readWord(mdata);
  ret.u49 = readWord(mdata);
  ret.u50 = readWord(mdata);
  ret.u51 = readWord(mdata);
  ret.u52 = readWord(mdata);

  printMonster(&ret);
  return ret;
}

int main(int argc, char** argv){
  char* datAbsolutePath;

  if(argc != 2){
    cerr << "Expected exactly one argument -- the absolute path to the MDATA5.MDR" << endl;
    return 1;
  }else{
    datAbsolutePath = argv[1];
  }

  if (not possiblyValidFile(datAbsolutePath, MDATA5)){
    cerr << datAbsolutePath << " doesn't appear to be a valid MDATA5.MDR" << endl;
    return 1;
  }

  return 0;
}
<|endoftext|>


<commit_before>// Undeprecate CRT functions
#ifndef _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE 1
#endif

#include "HandTracker.h"
#include "Segmentation.h"
#include <SenseKitUL/streams/hand_types.h>
#include <SenseKitUL/skul_ctypes.h>
#include <SenseKit/Plugins/PluginKit.h>

namespace sensekit { namespace plugins { namespace hand {

        using namespace std;

        const int PROCESSING_SIZE_WIDTH = 160;
        const int PROCESSING_SIZE_HEIGHT = 120;

        HandTracker::HandTracker(PluginServiceProxy& pluginService,
                                 Sensor& streamset,
                                 StreamDescription& depthDescription) :
            m_pluginService(pluginService),
            m_depthUtility(PROCESSING_SIZE_WIDTH, PROCESSING_SIZE_HEIGHT),
            m_reader(streamset.create_reader()),
            m_depthStream(nullptr)
        {
            create_streams(pluginService, streamset);

            subscribe_to_depth_stream(streamset, depthDescription);
        }

        HandTracker::~HandTracker()
        {
        }

        void HandTracker::create_streams(PluginServiceProxy& pluginService, Sensor streamset)
        {
            m_handStream = make_unique<HandStream>(pluginService, streamset, SENSEKIT_HANDS_MAX_HAND_COUNT);

            const int bytesPerPixel = 3;

            m_debugImageStream = make_unique<DebugHandStream>(pluginService,
                                                              streamset,
                                                              PROCESSING_SIZE_WIDTH,
                                                              PROCESSING_SIZE_HEIGHT,
                                                              bytesPerPixel);
        }

        void HandTracker::subscribe_to_depth_stream(Sensor& streamset, StreamDescription& depthDescription)
        {
            m_depthStream = m_reader.stream<DepthStream>(depthDescription.get_subtype());
            m_depthStream.start();

            m_pointProcessor = std::make_unique<PointProcessor>();

            m_reader.addListener(*this);
        }

        void HandTracker::on_frame_ready(StreamReader& reader, Frame& frame)
        {
            if (m_handStream->has_connections() ||
                m_debugImageStream->has_connections())
            {
                DepthFrame depthFrame = frame.get<DepthFrame>();

                update_tracking(depthFrame);
            }
        }

        void HandTracker::reset()
        {
            m_depthUtility.reset();
            m_pointProcessor.reset();
        }

        void HandTracker::update_tracking(DepthFrame& depthFrame)
        {
            m_depthUtility.processDepthToVelocitySignal(depthFrame, m_matDepth, m_matDepthFullSize, m_matVelocitySignal);

            track_points(m_matDepth, m_matDepthFullSize, m_matVelocitySignal);

            //use same frameIndex as source depth frame
            sensekit_frame_index_t frameIndex = depthFrame.frameIndex();

            if (m_handStream->has_connections())
            {
                generate_hand_frame(frameIndex);
            }

            if (m_debugImageStream->has_connections())
            {
                generate_hand_debug_image_frame(frameIndex);
            }
        }

        void HandTracker::track_points(cv::Mat& matDepth,
                                       cv::Mat& matDepthFullSize,
                                       cv::Mat& matVelocitySignal)
        {
            m_layerSegmentation = cv::Mat::zeros(matDepth.size(), CV_8UC1);
            m_layerScore = cv::Mat::zeros(matDepth.size(), CV_32FC1);
            m_layerEdgeDistance = cv::Mat::zeros(matDepth.size(), CV_32FC1);
            m_debugUpdateSegmentation = cv::Mat::zeros(matDepth.size(), CV_8UC1);
            m_debugCreateSegmentation = cv::Mat::zeros(matDepth.size(), CV_8UC1);
            m_debugRefineSegmentation = cv::Mat::zeros(matDepth.size(), CV_8UC1);
            m_updateForegroundSearched = cv::Mat::zeros(matDepth.size(), CV_8UC1);
            m_createForegroundSearched = cv::Mat::zeros(matDepth.size(), CV_8UC1);
            m_refineForegroundSearched = cv::Mat::zeros(matDepth.size(), CV_8UC1);
            m_debugUpdateScore = cv::Mat::zeros(matDepth.size(), CV_32FC1);
            m_debugCreateScore = cv::Mat::zeros(matDepth.size(), CV_32FC1);
            m_matDepthWindow = cv::Mat::zeros(m_matDepth.size(), CV_32FC1);
            m_refineSegmentation = cv::Mat::zeros(matDepth.size(), CV_8UC1);
            m_refineScore = cv::Mat::zeros(matDepth.size(), CV_32FC1);
            m_refineEdgeDistance = cv::Mat::zeros(matDepth.size(), CV_32FC1);

            bool debugLayersEnabled = m_debugImageStream->has_connections();

            TrackingMatrices updateMatrices(matDepthFullSize,
                                            matDepth,
                                            m_matArea,
                                            m_matAreaSqrt,
                                            m_matBasicScore,
                                            matVelocitySignal,
                                            m_updateForegroundSearched,
                                            m_layerSegmentation,
                                            m_layerScore,
                                            m_layerEdgeDistance,
                                            m_debugUpdateSegmentation,
                                            m_debugUpdateScore,
                                            debugLayersEnabled,
                                            m_depthStream.coordinateMapper());

            m_pointProcessor->initialize_common_calculations(updateMatrices);

            //Update existing points first so that if we lose a point, we might recover it in the "add new" stage below
            //without having at least one frame of a lost point.

            m_pointProcessor->updateTrackedPoints(updateMatrices);

            m_pointProcessor->removeDuplicatePoints();

            TrackingMatrices createMatrices(matDepthFullSize,
                                            matDepth,
                                            m_matArea,
                                            m_matAreaSqrt,
                                            m_matBasicScore,
                                            matVelocitySignal,
                                            m_createForegroundSearched,
                                            m_layerSegmentation,
                                            m_layerScore,
                                            m_layerEdgeDistance,
                                            m_debugCreateSegmentation,
                                            m_debugCreateScore,
                                            debugLayersEnabled,
                                            m_depthStream.coordinateMapper());

            //add new points (unless already tracking)
            if (!m_debugImageStream->use_mouse_probe())
            {
                cv::Point seedPosition;
                cv::Point nextSearchStart(0, 0);
                while (segmentation::find_next_velocity_seed_pixel(matVelocitySignal, m_createForegroundSearched, seedPosition, nextSearchStart))
                {
                    m_pointProcessor->updateTrackedPointOrCreateNewPointFromSeedPosition(createMatrices, seedPosition);
                }
            }
            else
            {
                auto normPosition = m_debugImageStream->mouse_norm_position();
                int x = MAX(0, MIN(PROCESSING_SIZE_WIDTH, normPosition.x * PROCESSING_SIZE_WIDTH));
                int y = MAX(0, MIN(PROCESSING_SIZE_HEIGHT, normPosition.y * PROCESSING_SIZE_HEIGHT));
                cv::Point seedPosition(x, y);
                m_pointProcessor->updateTrackedPointOrCreateNewPointFromSeedPosition(createMatrices, seedPosition);

                float area = m_pointProcessor->get_point_area(createMatrices, seedPosition);
                float depth = matDepth.at<float>(seedPosition);
                float edgeDist = m_layerEdgeDistance.at<float>(seedPosition);

                float foregroundRadius = 80;
                auto mapper = get_scaling_mapper(createMatrices);
                float percentForeground = segmentation::get_percent_foreground_along_circumference(matDepth,
                                                                                m_layerSegmentation,
                                                                                m_matAreaSqrt,
                                                                                seedPosition,
                                                                                foregroundRadius,
                                                                                mapper);
                printf("probe depth: %f area: %f fg_perc: %f edgeDist %f\n", depth, area, percentForeground, edgeDist);
            }

            //remove old points
            m_pointProcessor->removeOldOrDeadPoints();

            TrackingMatrices refinementMatrices(matDepthFullSize,
                                                m_matDepthWindow,
                                                m_matArea,
                                                m_matAreaSqrt,
                                                m_matBasicScore,
                                                matVelocitySignal,
                                                m_refineForegroundSearched,
                                                m_refineSegmentation,
                                                m_refineScore,
                                                m_refineEdgeDistance,
                                                m_debugRefineSegmentation,
                                                m_debugRefineScore,
                                                false,
                                                m_depthStream.coordinateMapper());

            m_pointProcessor->update_full_resolution_points(refinementMatrices);
        }

        void HandTracker::generate_hand_frame(sensekit_frame_index_t frameIndex)
        {
            sensekit_handframe_wrapper_t* handFrame = m_handStream->begin_write(frameIndex);

            if (handFrame != nullptr)
            {
                handFrame->frame.handpoints = reinterpret_cast<sensekit_handpoint_t*>(&(handFrame->frame_data));
                handFrame->frame.handCount = SENSEKIT_HANDS_MAX_HAND_COUNT;

                update_hand_frame(m_pointProcessor->get_trackedPoints(), handFrame->frame);

                m_handStream->end_write();
            }
        }

        void HandTracker::generate_hand_debug_image_frame(sensekit_frame_index_t frameIndex)
        {
            sensekit_imageframe_wrapper_t* debugImageFrame = m_debugImageStream->begin_write(frameIndex);

            if (debugImageFrame != nullptr)
            {
                debugImageFrame->frame.data = reinterpret_cast<uint8_t *>(&(debugImageFrame->frame_data));

                sensekit_image_metadata_t metadata;

                metadata.width = PROCESSING_SIZE_WIDTH;
                metadata.height = PROCESSING_SIZE_HEIGHT;
                metadata.bytesPerPixel = 3;

                debugImageFrame->frame.metadata = metadata;
                update_debug_image_frame(debugImageFrame->frame);

                m_debugImageStream->end_write();
            }
        }

        void HandTracker::update_hand_frame(vector<TrackedPoint>& internalTrackedPoints, _sensekit_handframe& frame)
        {
            int handIndex = 0;
            int maxHandCount = frame.handCount;

            bool includeCandidates = m_handStream->include_candidate_points();

            for (auto it = internalTrackedPoints.begin(); it != internalTrackedPoints.end(); ++it)
            {
                TrackedPoint internalPoint = *it;

                TrackingStatus status = internalPoint.trackingStatus;
                TrackedPointType pointType = internalPoint.pointType;

                bool includeByStatus = status == Tracking ||
                                       status == Lost;
                bool includeByType = pointType == ActivePoint ||
                                     (pointType == CandidatePoint && includeCandidates);
                if (includeByStatus && includeByType && handIndex < maxHandCount)
                {
                    sensekit_handpoint_t& point = frame.handpoints[handIndex];
                    ++handIndex;

                    point.trackingId = internalPoint.trackingId;

                    point.depthPosition.x = internalPoint.fullSizePosition.x;
                    point.depthPosition.y = internalPoint.fullSizePosition.y;

                    copy_position(internalPoint.fullSizeWorldPosition, point.worldPosition);
                    copy_position(internalPoint.fullSizeWorldDeltaPosition, point.worldDeltaPosition);

                    point.status = convert_hand_status(status, pointType);
                }
            }
            for (int i = handIndex; i < maxHandCount; ++i)
            {
                sensekit_handpoint_t& point = frame.handpoints[i];
                reset_hand_point(point);
            }
        }

        void HandTracker::copy_position(cv::Point3f& source, sensekit_vector3f_t& target)
        {
            target.x = source.x;
            target.y = source.y;
            target.z = source.z;
        }

        sensekit_handstatus_t HandTracker::convert_hand_status(TrackingStatus status, TrackedPointType type)
        {
            if (type == TrackedPointType::CandidatePoint)
            {
                return HAND_STATUS_CANDIDATE;
            }
            switch (status)
            {
            case Tracking:
                return HAND_STATUS_TRACKING;
                break;
            case Lost:
                return HAND_STATUS_LOST;
                break;
            case Dead:
            case NotTracking:
            default:
                return HAND_STATUS_NOTTRACKING;
                break;
            }
        }

        void HandTracker::reset_hand_point(sensekit_handpoint_t& point)
        {
            point.trackingId = -1;
            point.status = HAND_STATUS_NOTTRACKING;
            point.depthPosition = sensekit_vector2i_t();
            point.worldPosition = sensekit_vector3f_t();
            point.worldDeltaPosition = sensekit_vector3f_t();
        }

        void mark_image_pixel(_sensekit_imageframe& imageFrame,
                              RGBPixel color,
                              cv::Point p)
        {
            RGBPixel* colorData = static_cast<RGBPixel*>(imageFrame.data);
            int index = p.x + p.y * imageFrame.metadata.width;
            colorData[index] = color;
        }

        void HandTracker::overlay_circle(_sensekit_imageframe& imageFrame)
        {
            auto normPosition = m_debugImageStream->mouse_norm_position();
            int x = MAX(0, MIN(PROCESSING_SIZE_WIDTH, normPosition.x * PROCESSING_SIZE_WIDTH));
            int y = MAX(0, MIN(PROCESSING_SIZE_HEIGHT, normPosition.y * PROCESSING_SIZE_HEIGHT));

            float foregroundRadius = 80;
            float resizeFactor = m_matDepthFullSize.cols / static_cast<float>(m_matDepth.cols);
            ScalingCoordinateMapper mapper(m_depthStream.coordinateMapper(), resizeFactor);

            RGBPixel color(255, 0, 255);

            auto callback = [&](cv::Point p)
            {
                mark_image_pixel(imageFrame, color, p);
            };

            segmentation::visit_circle_circumference(m_matDepth, cv::Point(x, y), foregroundRadius, mapper, callback);
        }

        void HandTracker::update_debug_image_frame(_sensekit_imageframe& colorFrame)
        {
            float m_maxVelocity = 0.1;

            RGBPixel foregroundColor(0, 0, 255);
            RGBPixel searchedColor(128, 255, 0);

            DebugHandViewType view = m_debugImageStream->view_type();

            switch (view)
            {
            case DEBUG_HAND_VIEW_DEPTH:
                m_debugVisualizer.showDepthMat(m_matDepth,
                                               colorFrame);
                break;
            case DEBUG_HAND_VIEW_DEPTH_MOD:
                m_debugVisualizer.showDepthMat(m_depthUtility.matDepthFilled(),
                                               colorFrame);
                break;
            case DEBUG_HAND_VIEW_DEPTH_AVG:
                m_debugVisualizer.showDepthMat(m_depthUtility.matDepthAvg(),
                                               colorFrame);
                break;
            case DEBUG_HAND_VIEW_VELOCITY:
                m_debugVisualizer.showVelocityMat(m_depthUtility.matDepthVel(),
                                                  m_maxVelocity,
                                                  colorFrame);
                break;
            case DEBUG_HAND_VIEW_FILTEREDVELOCITY:
                m_debugVisualizer.showVelocityMat(m_depthUtility.matDepthVelErode(),
                                                  m_maxVelocity,
                                                  colorFrame);
                break;
            case DEBUG_HAND_VIEW_UPDATE_SEGMENTATION:
                m_debugVisualizer.showNormArray<char>(m_debugUpdateSegmentation,
                                                      m_debugUpdateSegmentation,
                                                      colorFrame);
                break;
            case DEBUG_HAND_VIEW_CREATE_SEGMENTATION:
                m_debugVisualizer.showNormArray<char>(m_debugCreateSegmentation,
                                                      m_debugCreateSegmentation,
                                                      colorFrame);
                break;
            case DEBUG_HAND_VIEW_UPDATE_SEARCHED:
            case DEBUG_HAND_VIEW_CREATE_SEARCHED:
                m_debugVisualizer.showDepthMat(m_matDepth,
                                               colorFrame);
                break;
            case DEBUG_HAND_VIEW_CREATE_SCORE:
                m_debugVisualizer.showNormArray<float>(m_debugCreateScore,
                                                       m_debugCreateSegmentation,
                                                       colorFrame);
                break;
            case DEBUG_HAND_VIEW_UPDATE_SCORE:
                m_debugVisualizer.showNormArray<float>(m_debugUpdateScore,
                                                       m_debugUpdateSegmentation,
                                                       colorFrame);
                break;
            case DEBUG_HAND_VIEW_HANDWINDOW:
                m_debugVisualizer.showDepthMat(m_matDepthWindow,
                                               colorFrame);
                break;
            }

            if (view != DEBUG_HAND_VIEW_HANDWINDOW &&
                view != DEBUG_HAND_VIEW_CREATE_SCORE &&
                view != DEBUG_HAND_VIEW_UPDATE_SCORE &&
                view != DEBUG_HAND_VIEW_DEPTH_MOD &&
                view != DEBUG_HAND_VIEW_DEPTH_AVG)
            {
                if (view == DEBUG_HAND_VIEW_CREATE_SEARCHED)
                {
                    m_debugVisualizer.overlayMask(m_createForegroundSearched, colorFrame, searchedColor);
                }
                else if (view == DEBUG_HAND_VIEW_UPDATE_SEARCHED)
                {
                    m_debugVisualizer.overlayMask(m_updateForegroundSearched, colorFrame, searchedColor);
                }

                m_debugVisualizer.overlayMask(m_matVelocitySignal, colorFrame, foregroundColor);
            }

            if (m_debugImageStream->use_mouse_probe())
            {
                overlay_circle(colorFrame);
            }
        }
}}}<commit_msg>Dual radius visuals<commit_after>// Undeprecate CRT functions
#ifndef _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE 1
#endif

#include "HandTracker.h"
#include "Segmentation.h"
#include <SenseKitUL/streams/hand_types.h>
#include <SenseKitUL/skul_ctypes.h>
#include <SenseKit/Plugins/PluginKit.h>

namespace sensekit { namespace plugins { namespace hand {

        using namespace std;

        const int PROCESSING_SIZE_WIDTH = 160;
        const int PROCESSING_SIZE_HEIGHT = 120;

        HandTracker::HandTracker(PluginServiceProxy& pluginService,
                                 Sensor& streamset,
                                 StreamDescription& depthDescription) :
            m_pluginService(pluginService),
            m_depthUtility(PROCESSING_SIZE_WIDTH, PROCESSING_SIZE_HEIGHT),
            m_reader(streamset.create_reader()),
            m_depthStream(nullptr)
        {
            create_streams(pluginService, streamset);

            subscribe_to_depth_stream(streamset, depthDescription);
        }

        HandTracker::~HandTracker()
        {
        }

        void HandTracker::create_streams(PluginServiceProxy& pluginService, Sensor streamset)
        {
            m_handStream = make_unique<HandStream>(pluginService, streamset, SENSEKIT_HANDS_MAX_HAND_COUNT);

            const int bytesPerPixel = 3;

            m_debugImageStream = make_unique<DebugHandStream>(pluginService,
                                                              streamset,
                                                              PROCESSING_SIZE_WIDTH,
                                                              PROCESSING_SIZE_HEIGHT,
                                                              bytesPerPixel);
        }

        void HandTracker::subscribe_to_depth_stream(Sensor& streamset, StreamDescription& depthDescription)
        {
            m_depthStream = m_reader.stream<DepthStream>(depthDescription.get_subtype());
            m_depthStream.start();

            m_pointProcessor = std::make_unique<PointProcessor>();

            m_reader.addListener(*this);
        }

        void HandTracker::on_frame_ready(StreamReader& reader, Frame& frame)
        {
            if (m_handStream->has_connections() ||
                m_debugImageStream->has_connections())
            {
                DepthFrame depthFrame = frame.get<DepthFrame>();

                update_tracking(depthFrame);
            }
        }

        void HandTracker::reset()
        {
            m_depthUtility.reset();
            m_pointProcessor.reset();
        }

        void HandTracker::update_tracking(DepthFrame& depthFrame)
        {
            m_depthUtility.processDepthToVelocitySignal(depthFrame, m_matDepth, m_matDepthFullSize, m_matVelocitySignal);

            track_points(m_matDepth, m_matDepthFullSize, m_matVelocitySignal);

            //use same frameIndex as source depth frame
            sensekit_frame_index_t frameIndex = depthFrame.frameIndex();

            if (m_handStream->has_connections())
            {
                generate_hand_frame(frameIndex);
            }

            if (m_debugImageStream->has_connections())
            {
                generate_hand_debug_image_frame(frameIndex);
            }
        }

        void HandTracker::track_points(cv::Mat& matDepth,
                                       cv::Mat& matDepthFullSize,
                                       cv::Mat& matVelocitySignal)
        {
            m_layerSegmentation = cv::Mat::zeros(matDepth.size(), CV_8UC1);
            m_layerScore = cv::Mat::zeros(matDepth.size(), CV_32FC1);
            m_layerEdgeDistance = cv::Mat::zeros(matDepth.size(), CV_32FC1);
            m_debugUpdateSegmentation = cv::Mat::zeros(matDepth.size(), CV_8UC1);
            m_debugCreateSegmentation = cv::Mat::zeros(matDepth.size(), CV_8UC1);
            m_debugRefineSegmentation = cv::Mat::zeros(matDepth.size(), CV_8UC1);
            m_updateForegroundSearched = cv::Mat::zeros(matDepth.size(), CV_8UC1);
            m_createForegroundSearched = cv::Mat::zeros(matDepth.size(), CV_8UC1);
            m_refineForegroundSearched = cv::Mat::zeros(matDepth.size(), CV_8UC1);
            m_debugUpdateScore = cv::Mat::zeros(matDepth.size(), CV_32FC1);
            m_debugCreateScore = cv::Mat::zeros(matDepth.size(), CV_32FC1);
            m_matDepthWindow = cv::Mat::zeros(m_matDepth.size(), CV_32FC1);
            m_refineSegmentation = cv::Mat::zeros(matDepth.size(), CV_8UC1);
            m_refineScore = cv::Mat::zeros(matDepth.size(), CV_32FC1);
            m_refineEdgeDistance = cv::Mat::zeros(matDepth.size(), CV_32FC1);

            bool debugLayersEnabled = m_debugImageStream->has_connections();

            TrackingMatrices updateMatrices(matDepthFullSize,
                                            matDepth,
                                            m_matArea,
                                            m_matAreaSqrt,
                                            m_matBasicScore,
                                            matVelocitySignal,
                                            m_updateForegroundSearched,
                                            m_layerSegmentation,
                                            m_layerScore,
                                            m_layerEdgeDistance,
                                            m_debugUpdateSegmentation,
                                            m_debugUpdateScore,
                                            debugLayersEnabled,
                                            m_depthStream.coordinateMapper());

            m_pointProcessor->initialize_common_calculations(updateMatrices);

            //Update existing points first so that if we lose a point, we might recover it in the "add new" stage below
            //without having at least one frame of a lost point.

            m_pointProcessor->updateTrackedPoints(updateMatrices);

            m_pointProcessor->removeDuplicatePoints();

            TrackingMatrices createMatrices(matDepthFullSize,
                                            matDepth,
                                            m_matArea,
                                            m_matAreaSqrt,
                                            m_matBasicScore,
                                            matVelocitySignal,
                                            m_createForegroundSearched,
                                            m_layerSegmentation,
                                            m_layerScore,
                                            m_layerEdgeDistance,
                                            m_debugCreateSegmentation,
                                            m_debugCreateScore,
                                            debugLayersEnabled,
                                            m_depthStream.coordinateMapper());

            //add new points (unless already tracking)
            if (!m_debugImageStream->use_mouse_probe())
            {
                cv::Point seedPosition;
                cv::Point nextSearchStart(0, 0);
                while (segmentation::find_next_velocity_seed_pixel(matVelocitySignal, m_createForegroundSearched, seedPosition, nextSearchStart))
                {
                    m_pointProcessor->updateTrackedPointOrCreateNewPointFromSeedPosition(createMatrices, seedPosition);
                }
            }
            else
            {
                auto normPosition = m_debugImageStream->mouse_norm_position();
                int x = MAX(0, MIN(PROCESSING_SIZE_WIDTH, normPosition.x * PROCESSING_SIZE_WIDTH));
                int y = MAX(0, MIN(PROCESSING_SIZE_HEIGHT, normPosition.y * PROCESSING_SIZE_HEIGHT));
                cv::Point seedPosition(x, y);
                m_pointProcessor->updateTrackedPointOrCreateNewPointFromSeedPosition(createMatrices, seedPosition);

                float area = m_pointProcessor->get_point_area(createMatrices, seedPosition);
                float depth = matDepth.at<float>(seedPosition);
                float edgeDist = m_layerEdgeDistance.at<float>(seedPosition);

                float foregroundRadius1 = 100;
                float foregroundRadius2 = 150;
                auto mapper = get_scaling_mapper(createMatrices);
                float percentForeground1 = segmentation::get_percent_foreground_along_circumference(matDepth,
                                                                                m_layerSegmentation,
                                                                                m_matAreaSqrt,
                                                                                seedPosition,
                                                                                foregroundRadius1,
                                                                                mapper);
                float percentForeground2 = segmentation::get_percent_foreground_along_circumference(matDepth,
                                                                                m_layerSegmentation,
                                                                                m_matAreaSqrt,
                                                                                seedPosition,
                                                                                foregroundRadius2,
                                                                                mapper);
                printf("depth: %f area: %f fg1: %f fg2: %f edge: %f\n", depth,
                                                                        area,
                                                                        percentForeground1,
                                                                        percentForeground2,
                                                                        edgeDist);
            }

            //remove old points
            m_pointProcessor->removeOldOrDeadPoints();

            TrackingMatrices refinementMatrices(matDepthFullSize,
                                                m_matDepthWindow,
                                                m_matArea,
                                                m_matAreaSqrt,
                                                m_matBasicScore,
                                                matVelocitySignal,
                                                m_refineForegroundSearched,
                                                m_refineSegmentation,
                                                m_refineScore,
                                                m_refineEdgeDistance,
                                                m_debugRefineSegmentation,
                                                m_debugRefineScore,
                                                false,
                                                m_depthStream.coordinateMapper());

            m_pointProcessor->update_full_resolution_points(refinementMatrices);
        }

        void HandTracker::generate_hand_frame(sensekit_frame_index_t frameIndex)
        {
            sensekit_handframe_wrapper_t* handFrame = m_handStream->begin_write(frameIndex);

            if (handFrame != nullptr)
            {
                handFrame->frame.handpoints = reinterpret_cast<sensekit_handpoint_t*>(&(handFrame->frame_data));
                handFrame->frame.handCount = SENSEKIT_HANDS_MAX_HAND_COUNT;

                update_hand_frame(m_pointProcessor->get_trackedPoints(), handFrame->frame);

                m_handStream->end_write();
            }
        }

        void HandTracker::generate_hand_debug_image_frame(sensekit_frame_index_t frameIndex)
        {
            sensekit_imageframe_wrapper_t* debugImageFrame = m_debugImageStream->begin_write(frameIndex);

            if (debugImageFrame != nullptr)
            {
                debugImageFrame->frame.data = reinterpret_cast<uint8_t *>(&(debugImageFrame->frame_data));

                sensekit_image_metadata_t metadata;

                metadata.width = PROCESSING_SIZE_WIDTH;
                metadata.height = PROCESSING_SIZE_HEIGHT;
                metadata.bytesPerPixel = 3;

                debugImageFrame->frame.metadata = metadata;
                update_debug_image_frame(debugImageFrame->frame);

                m_debugImageStream->end_write();
            }
        }

        void HandTracker::update_hand_frame(vector<TrackedPoint>& internalTrackedPoints, _sensekit_handframe& frame)
        {
            int handIndex = 0;
            int maxHandCount = frame.handCount;

            bool includeCandidates = m_handStream->include_candidate_points();

            for (auto it = internalTrackedPoints.begin(); it != internalTrackedPoints.end(); ++it)
            {
                TrackedPoint internalPoint = *it;

                TrackingStatus status = internalPoint.trackingStatus;
                TrackedPointType pointType = internalPoint.pointType;

                bool includeByStatus = status == Tracking ||
                                       status == Lost;
                bool includeByType = pointType == ActivePoint ||
                                     (pointType == CandidatePoint && includeCandidates);
                if (includeByStatus && includeByType && handIndex < maxHandCount)
                {
                    sensekit_handpoint_t& point = frame.handpoints[handIndex];
                    ++handIndex;

                    point.trackingId = internalPoint.trackingId;

                    point.depthPosition.x = internalPoint.fullSizePosition.x;
                    point.depthPosition.y = internalPoint.fullSizePosition.y;

                    copy_position(internalPoint.fullSizeWorldPosition, point.worldPosition);
                    copy_position(internalPoint.fullSizeWorldDeltaPosition, point.worldDeltaPosition);

                    point.status = convert_hand_status(status, pointType);
                }
            }
            for (int i = handIndex; i < maxHandCount; ++i)
            {
                sensekit_handpoint_t& point = frame.handpoints[i];
                reset_hand_point(point);
            }
        }

        void HandTracker::copy_position(cv::Point3f& source, sensekit_vector3f_t& target)
        {
            target.x = source.x;
            target.y = source.y;
            target.z = source.z;
        }

        sensekit_handstatus_t HandTracker::convert_hand_status(TrackingStatus status, TrackedPointType type)
        {
            if (type == TrackedPointType::CandidatePoint)
            {
                return HAND_STATUS_CANDIDATE;
            }
            switch (status)
            {
            case Tracking:
                return HAND_STATUS_TRACKING;
                break;
            case Lost:
                return HAND_STATUS_LOST;
                break;
            case Dead:
            case NotTracking:
            default:
                return HAND_STATUS_NOTTRACKING;
                break;
            }
        }

        void HandTracker::reset_hand_point(sensekit_handpoint_t& point)
        {
            point.trackingId = -1;
            point.status = HAND_STATUS_NOTTRACKING;
            point.depthPosition = sensekit_vector2i_t();
            point.worldPosition = sensekit_vector3f_t();
            point.worldDeltaPosition = sensekit_vector3f_t();
        }

        void mark_image_pixel(_sensekit_imageframe& imageFrame,
                              RGBPixel color,
                              cv::Point p)
        {
            RGBPixel* colorData = static_cast<RGBPixel*>(imageFrame.data);
            int index = p.x + p.y * imageFrame.metadata.width;
            colorData[index] = color;
        }

        void HandTracker::overlay_circle(_sensekit_imageframe& imageFrame)
        {
            auto normPosition = m_debugImageStream->mouse_norm_position();
            int x = MAX(0, MIN(PROCESSING_SIZE_WIDTH, normPosition.x * PROCESSING_SIZE_WIDTH));
            int y = MAX(0, MIN(PROCESSING_SIZE_HEIGHT, normPosition.y * PROCESSING_SIZE_HEIGHT));

            float foregroundRadius1 = 100;
            float foregroundRadius2 = 150;

            float resizeFactor = m_matDepthFullSize.cols / static_cast<float>(m_matDepth.cols);
            ScalingCoordinateMapper mapper(m_depthStream.coordinateMapper(), resizeFactor);

            RGBPixel color(255, 0, 255);

            auto callback = [&](cv::Point p)
            {
                mark_image_pixel(imageFrame, color, p);
            };

            segmentation::visit_circle_circumference(m_matDepth, cv::Point(x, y), foregroundRadius1, mapper, callback);
            segmentation::visit_circle_circumference(m_matDepth, cv::Point(x, y), foregroundRadius2, mapper, callback);
        }

        void HandTracker::update_debug_image_frame(_sensekit_imageframe& colorFrame)
        {
            float m_maxVelocity = 0.1;

            RGBPixel foregroundColor(0, 0, 255);
            RGBPixel searchedColor(128, 255, 0);

            DebugHandViewType view = m_debugImageStream->view_type();

            switch (view)
            {
            case DEBUG_HAND_VIEW_DEPTH:
                m_debugVisualizer.showDepthMat(m_matDepth,
                                               colorFrame);
                break;
            case DEBUG_HAND_VIEW_DEPTH_MOD:
                m_debugVisualizer.showDepthMat(m_depthUtility.matDepthFilled(),
                                               colorFrame);
                break;
            case DEBUG_HAND_VIEW_DEPTH_AVG:
                m_debugVisualizer.showDepthMat(m_depthUtility.matDepthAvg(),
                                               colorFrame);
                break;
            case DEBUG_HAND_VIEW_VELOCITY:
                m_debugVisualizer.showVelocityMat(m_depthUtility.matDepthVel(),
                                                  m_maxVelocity,
                                                  colorFrame);
                break;
            case DEBUG_HAND_VIEW_FILTEREDVELOCITY:
                m_debugVisualizer.showVelocityMat(m_depthUtility.matDepthVelErode(),
                                                  m_maxVelocity,
                                                  colorFrame);
                break;
            case DEBUG_HAND_VIEW_UPDATE_SEGMENTATION:
                m_debugVisualizer.showNormArray<char>(m_debugUpdateSegmentation,
                                                      m_debugUpdateSegmentation,
                                                      colorFrame);
                break;
            case DEBUG_HAND_VIEW_CREATE_SEGMENTATION:
                m_debugVisualizer.showNormArray<char>(m_debugCreateSegmentation,
                                                      m_debugCreateSegmentation,
                                                      colorFrame);
                break;
            case DEBUG_HAND_VIEW_UPDATE_SEARCHED:
            case DEBUG_HAND_VIEW_CREATE_SEARCHED:
                m_debugVisualizer.showDepthMat(m_matDepth,
                                               colorFrame);
                break;
            case DEBUG_HAND_VIEW_CREATE_SCORE:
                m_debugVisualizer.showNormArray<float>(m_debugCreateScore,
                                                       m_debugCreateSegmentation,
                                                       colorFrame);
                break;
            case DEBUG_HAND_VIEW_UPDATE_SCORE:
                m_debugVisualizer.showNormArray<float>(m_debugUpdateScore,
                                                       m_debugUpdateSegmentation,
                                                       colorFrame);
                break;
            case DEBUG_HAND_VIEW_HANDWINDOW:
                m_debugVisualizer.showDepthMat(m_matDepthWindow,
                                               colorFrame);
                break;
            }

            if (view != DEBUG_HAND_VIEW_HANDWINDOW &&
                view != DEBUG_HAND_VIEW_CREATE_SCORE &&
                view != DEBUG_HAND_VIEW_UPDATE_SCORE &&
                view != DEBUG_HAND_VIEW_DEPTH_MOD &&
                view != DEBUG_HAND_VIEW_DEPTH_AVG)
            {
                if (view == DEBUG_HAND_VIEW_CREATE_SEARCHED)
                {
                    m_debugVisualizer.overlayMask(m_createForegroundSearched, colorFrame, searchedColor);
                }
                else if (view == DEBUG_HAND_VIEW_UPDATE_SEARCHED)
                {
                    m_debugVisualizer.overlayMask(m_updateForegroundSearched, colorFrame, searchedColor);
                }

                m_debugVisualizer.overlayMask(m_matVelocitySignal, colorFrame, foregroundColor);
            }

            if (m_debugImageStream->use_mouse_probe())
            {
                overlay_circle(colorFrame);
            }
        }
}}}<|endoftext|>