示例#1
0
void writeIndexes(std::string A_indexFile, std::string B_indexFile, std::string oldDBIndex, std::string newDBIndex){

    FILE* A_index_file = fopen(A_indexFile.c_str(), "w");
    FILE* B_index_file = fopen(B_indexFile.c_str(), "w");

    ffindex_index_t* index_old = openIndex(oldDBIndex.c_str());
    ffindex_index_t* index_new = openIndex(newDBIndex.c_str());

    // positions in the databases
    unsigned int i = 0;
    unsigned int j = 0;

    int deleted_cnt = 0;
    int new_cnt = 0;
    int shared_cnt = 0;
    while (i < index_old->n_entries && j < index_new->n_entries){
        ffindex_entry_t* e_i = ffindex_get_entry_by_index(index_old, i);
        ffindex_entry_t* e_j = ffindex_get_entry_by_index(index_new, j);
        int cmp = strcmp(&(e_i->name[0]), &(e_j->name[0]));
        if (cmp == 0){
            // this sequence is in both databases
            fprintf(A_index_file, "%s\t%zd\t%zd\n", e_j->name, e_j->offset, e_j->length);
            shared_cnt++;
            i++;
            j++;
        }
        else if (cmp < 0){
            // sequence was deleted from the old database
            deleted_cnt++;
            i++;
        }
        else{
            // this sequence is new
            fprintf(B_index_file, "%s\t%zd\t%zd\n", e_j->name, e_j->offset, e_j->length);
            new_cnt++;
            j++;
        }
    }
    while (i < index_old->n_entries){
        deleted_cnt++;
        i++;
    }
    // add the rest of the new database to the new sequences
    while (j < index_new->n_entries){
        ffindex_entry_t* e_j = ffindex_get_entry_by_index(index_new, j);
        fprintf(B_index_file, "%s\t%zd\t%zd\n", e_j->name, e_j->offset, e_j->length);
        new_cnt++;
        j++;
    }

    // set the global count variables
    oldDBSize = index_old->n_entries;
    newDBSize = index_new->n_entries;
    deletedSeqs = deleted_cnt;
    sharedSeqs = shared_cnt;
    newSeqs = new_cnt;

    fclose(A_index_file);
    fclose(B_index_file);
}
/**
 * Open a document collection.
 */
int
YASENS Collection::open(const char *home, const char *mode)
{
	tree = openIndex( home, mode );
	if (tree == 0) {
		snprintf(errmsg, sizeof errmsg, "Error: cannot open YASE Index\n");
		return -1;
	}

	docdb = ys_dbopen( home, mode, "" );
	if (docdb == NULL) {
		snprintf(errmsg, sizeof errmsg, "Error: cannot open YASE files\n");
		return -1;
	}
	else {
		ys_docnum_t N = 0, numfiles;
		ys_doccnt_t maxdoctermfreq, maxtermfreq;
		ys_bool_t stemmed;
		ys_dbgetinfo(docdb, &N, &numfiles,
			&maxdoctermfreq, &maxtermfreq, &stemmed);
		this->N = N;
		this->stemmed = stemmed;
		this->maxtf = maxtermfreq;
		this->maxdtf = maxdoctermfreq;
		this->numFiles = numfiles;
	}

	postings_file = openPostings( home, mode );
	if (postings_file == 0) {
		snprintf(errmsg, sizeof errmsg, "Error: cannot open Postings file\n" );
		return -1;
	}

	return 0;
}
示例#3
0
//Cria lista de indices a partir do arquivo de indices
void getAllIndexesOnFile(indice **lista)
{
  if(openIndex())
  { 
    int tam = getIndexCount();
    int count=0;
    
    fseek(ind,4,SEEK_SET);
    
    while(count<tam)
    {
        indice *i=(indice *)malloc(sizeof(indice));

        fread(&i->id_locacao,sizeof(int),1,ind);
        fread(&i->offset,sizeof(int),1,ind);
        i->prox=NULL;
        
        insertIndexOnList(lista,i);
        
        count++; 
    }
  }
  
  closeIndex();
}
示例#4
0
//Insere um indice no arquivo de indices
void insertIndexOnFile(indice *index)
{
  if(openIndex())
  {
    //Altera o cabeçalho com o contador da lista
    fseek(ind,0,SEEK_SET);
    
    int head=0;
    fread(&head,sizeof(int),1,ind);
    
    int cont=head;
    cont=cont+1;
    fseek(ind,0,SEEK_SET);
    fwrite(&cont,sizeof(int),1,ind);
    
    fflush(ind);
    
    //insere o indice
    fseek(ind,0,SEEK_END);
    fwrite(&index->id_locacao,sizeof(int),1,ind);
    fwrite(&index->offset,sizeof(int),1,ind);
  }
  
  closeIndex();
}
示例#5
0
//Remove indice do arquivo de indices
void removeIndexFromFile(indice *i,indice **lista)
{
  if(openIndex())
  {
  //zera o contador da lista
  fseek(ind,0,SEEK_SET);
  
  int cont=0;
  
  //insere os indices, menos o que foi excluido
  fseek(ind,4,SEEK_SET);
  
  while(*lista!=NULL)
  {
    if((*lista)->id_locacao!=i->id_locacao)
    {
      fwrite(&(*lista)->id_locacao,sizeof(int),1,ind);
      fwrite(&(*lista)->offset,sizeof(int),1,ind);
      cont++;
    }
    
    *lista = (*lista)->prox;
  }
  
  fseek(ind,0,SEEK_SET);
  fwrite(&cont,sizeof(int),1,ind);
  fflush(ind);
  }
  
  closeIndex();
}
示例#6
0
void appendToClustering(DBReader* currSeqDbr, std::string BIndexFile, std::string BA_base, unsigned int* id2rep, cluster_t* clusters, std::string Brest_indexFile){

    DBReader* BADbr = new DBReader(BA_base.c_str(), (BA_base + ".index").c_str());
    BADbr->open(DBReader::NOSORT);

    ffindex_index_t* Bindex = openIndex(BIndexFile.c_str());

    FILE* Brest_index_file = fopen(Brest_indexFile.c_str(), "w");

    seqsWithMatches = 0;
    seqsWithoutMatches = 0;
    char* buf = new char[1000000];
    for (unsigned int i = 0; i < BADbr->getSize(); i++){
        char* qKey = BADbr->getDbKey(i);
        unsigned int qId = currSeqDbr->getId(qKey);

        // find out which cluster the sequence belongs to
        char* alnData = BADbr->getData(i);
        strcpy(buf, alnData);

        char* tKey = strtok(buf, "\t");
        if (tKey != 0){
            unsigned int tId = currSeqDbr->getId(tKey);
            if (tId == UINT_MAX){
                std::cerr << "ERROR: DB key " << tKey << " is in the B->A alignment lists, but not in the new database!\n";
                exit(EXIT_FAILURE);
            }
            // find out the representative sequence of the cluster of the hit
            int repId = id2rep[tId];

            if(repId == -1){
                std::cout << "ERROR: database sequence " << tKey << " is not in the clustering!\n";
                std::cout << "Query from B: " << qKey << " matched this sequence.\n";
                continue;
            }

            // append new member to the cluster
            clu_entry_t* curr = new clu_entry_t; 
            curr->id = qId;
            curr->next = 0;

            clusters[repId].last->next = curr;
            clusters[repId].last = curr;
            clusters[repId].clu_size++;

            seqsWithMatches++;
        }
        else{
            ffindex_entry_t* e = ffindex_get_entry_by_name(Bindex, qKey);
            fprintf(Brest_index_file, "%s\t%zd\t%zd\n", e->name, e->offset, e->length);

            seqsWithoutMatches++;
        }
    }

    BADbr->close();
    fclose(Brest_index_file);
}
示例#7
0
void KMyMoneyAccountTreeView::keyPressEvent(QKeyEvent *event)
{
  if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) {
    openIndex(currentIndex());
    event->accept();
  } else {
    QTreeView::keyPressEvent(event);
  }
}
示例#8
0
//zera o contador de indice
void emptyIndex()
{
  if(openIndex())
  {
    //Coloca o ponteiro no cabeçalho do arquivo
    fseek(ind,0,SEEK_SET);
  
    //nula a lista de espaços disponiveis
    int nullValue=0;
    fwrite(&nullValue,sizeof(int),1,ind);
  }
  
  closeIndex();
}
示例#9
0
HelpWindow::HelpWindow(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::HelpWindow)
{
    textBrowser = new QTextBrowser(this);


    this->setWindowFlags(Qt::Tool|Qt::CustomizeWindowHint|
                         Qt::WindowTitleHint|
                         Qt::WindowMinMaxButtonsHint|Qt::WindowCloseButtonHint|Qt::WindowStaysOnTopHint);

    QStringList sl;

    use_settings;

    sl << settings.value("helpPath","").toString();
    sl << QCoreApplication::applicationDirPath() + "/doc";
    sl << QCoreApplication::applicationDirPath() + "/help";

    textBrowser->setSearchPaths ( sl );

    textBrowser->setSource(QUrl("index.html"));

    QPushButton * pbnext = new QPushButton(">>",this);
    QPushButton * pbpred = new QPushButton("<<",this);
    QPushButton * pbhome = new QPushButton(tr("Content"),this);


    QHBoxLayout * blay = new QHBoxLayout();
    blay->addWidget(pbpred);
    blay->addWidget(pbnext);
    blay->addStretch(10);
    blay->addWidget(pbhome);

    connect(pbpred,SIGNAL(clicked()),textBrowser,SLOT(backward()));
    connect(pbnext,SIGNAL(clicked()),textBrowser,SLOT(forward()));
    connect(pbhome,SIGNAL(clicked()),this,SLOT(openIndex()));


    QVBoxLayout * lay = new QVBoxLayout();

   lay->addLayout(blay);
   lay->addWidget(textBrowser);

   this->setLayout(lay);



    ui->setupUi(this);
}
示例#10
0
bool OsmAnd::TileDB::rebuildIndex()
{
    QMutexLocker scopeLock(&_indexMutex);

    bool ok;

    // Open index database if it's not yet
    if(!_indexDb.isOpen())
    {
        if(!openIndex())
            return false;
    }
    QSqlQuery q(_indexDb);

    LogPrintf(LogSeverityLevel::Info, "Rebuilding index of '%s' tiledb...", dataPath.absolutePath().toStdString().c_str());
    auto beginTimestamp = std::chrono::steady_clock::now();

    // Recreate index db structure
    if(!indexFilename.isEmpty())
    {
        ok = q.exec("DROP TABLE IF EXISTS tiledb_files");
        assert(ok);
        ok = q.exec("DROP TABLE IF EXISTS tiledb_index");
        assert(ok);
        ok = q.exec("DROP INDEX IF EXISTS _tiledb_index");
        assert(ok);
    }
    ok = q.exec(
        "CREATE TABLE tiledb_files ("
        "    id INTEGER PRIMARY KEY AUTOINCREMENT,"
        "    filename TEXT"
        ")");
    assert(ok);
    ok = q.exec(
        "CREATE TABLE tiledb_index ("
        "    xMin INTEGER,"
        "    yMin INTEGER,"
        "    xMax INTEGER,"
        "    yMax INTEGER,"
        "    zoom INTEGER,"
        "    id INTEGER"
        ")");
    assert(ok);
    ok = q.exec(
        "CREATE INDEX _tiledb_index"
        "    ON tiledb_index(xMin, yMin, xMax, yMax, zoom)");
    assert(ok);
    _indexDb.commit();

    QSqlQuery registerFileQuery(_indexDb);
    ok = registerFileQuery.prepare("INSERT INTO tiledb_files (filename) VALUES ( ? )");
    assert(ok);

    QSqlQuery insertTileQuery(_indexDb);
    ok = insertTileQuery.prepare("INSERT INTO tiledb_index (xMin, yMin, xMax, yMax, zoom, id) VALUES ( ?, ?, ?, ?, ?, ? )");
    assert(ok);

    // Index TileDBs
    QFileInfoList files;
    Utilities::findFiles(dataPath, QStringList() << "*", files);
    for(auto itFile = files.cbegin(); itFile != files.cend(); ++itFile)
    {
        const auto& file = *itFile;
        const auto dbFilename = file.absoluteFilePath();

        const auto connectionName = QString::fromLatin1("tiledb-sqlite:") + dbFilename;
        QSqlDatabase db;
        if(!QSqlDatabase::contains(connectionName))
            db = QSqlDatabase::addDatabase("QSQLITE", connectionName);
        else
            db = QSqlDatabase::database(connectionName);
        db.setDatabaseName(dbFilename);
        if(!db.open())
        {
            LogPrintf(LogSeverityLevel::Error, "Failed to open TileDB from '%s': %s", qPrintable(dbFilename), qPrintable(db.lastError().text()));
            continue;
        }

        // Register new file
        registerFileQuery.addBindValue(dbFilename);
        ok = registerFileQuery.exec();
        assert(ok);
        auto fileId = registerFileQuery.lastInsertId();

        // For each zoom, query min-max of tile coordinates
        QSqlQuery minMaxQuery("SELECT zoom, xMin, yMin, xMax, yMax FROM bounds", db);
        ok = minMaxQuery.exec();
        assert(ok);
        while(minMaxQuery.next())
        {
            int32_t zoom = minMaxQuery.value(0).toInt();
            int32_t xMin = minMaxQuery.value(1).toInt();
            int32_t yMin = minMaxQuery.value(2).toInt();
            int32_t xMax = minMaxQuery.value(3).toInt();
            int32_t yMax = minMaxQuery.value(4).toInt();

            insertTileQuery.addBindValue(xMin);
            insertTileQuery.addBindValue(yMin);
            insertTileQuery.addBindValue(xMax);
            insertTileQuery.addBindValue(yMax);
            insertTileQuery.addBindValue(zoom);
            insertTileQuery.addBindValue(fileId);

            ok = insertTileQuery.exec();
            assert(ok);
        }

        db.close();
    }

    _indexDb.commit();

    auto endTimestamp = std::chrono::steady_clock::now();
    auto duration = std::chrono::duration_cast< std::chrono::duration<uint64_t, std::milli> >(endTimestamp - beginTimestamp).count();
    LogPrintf(LogSeverityLevel::Info, "Finished indexing '%s', took %lldms, average %lldms/db", dataPath.absolutePath().toStdString().c_str(), duration, duration / files.length());

    return true;
}
示例#11
0
bool OsmAnd::TileDB::obtainTileData( const TileId& tileId, const ZoomLevel& zoom, QByteArray& data )
{
    QMutexLocker scopeLock(&_indexMutex);

    // Check that index is available
    if(!_indexDb.isOpen())
    {
        if(!openIndex())
            return false;
    }

    QSqlQuery query(_indexDb);
    query.prepare("SELECT filename FROM tiledb_files WHERE id IN (SELECT id FROM tiledb_index WHERE xMin<=? AND xMax>=? AND yMin<=? AND yMax>=? AND zoom=?)");
    query.addBindValue(tileId.x);
    query.addBindValue(tileId.x);
    query.addBindValue(tileId.y);
    query.addBindValue(tileId.y);
    query.addBindValue(zoom);
    if(!query.exec())
        return false;

    bool hit = false;
    while(!hit && query.next())
    {
        const auto dbFilename = query.value(0).toString();

        //TODO: manage access to database
        //QMutexLocker scopeLock(&dbEntry->mutex);

        // Open database
        const auto connectionName = QString::fromLatin1("tiledb-sqlite:") + dbFilename;
        QSqlDatabase db;
        if(!QSqlDatabase::contains(connectionName))
            db = QSqlDatabase::addDatabase("QSQLITE", connectionName);
        else
            db = QSqlDatabase::database(connectionName);
        db.setDatabaseName(dbFilename);
        if(!db.open())
        {
            LogPrintf(LogSeverityLevel::Error, "Failed to open TileDB index from '%s': %s", qPrintable(dbFilename), qPrintable(db.lastError().text()));
            return false;
        }

        // Get tile from
        QSqlQuery query(db);
        query.prepare("SELECT data FROM tiles WHERE x=? AND y=? AND zoom=?");
        query.addBindValue(tileId.x);
        query.addBindValue(tileId.y);
        query.addBindValue(static_cast<int>(zoom));
        if(query.exec() && query.next())
        {
            data = query.value(0).toByteArray();
            hit = true;
        }

        // Close database
        db.close();
    }
    
    return hit;
}
示例#12
0
void KMyMoneyAccountTreeView::mouseDoubleClickEvent(QMouseEvent *event)
{
  openIndex(currentIndex());
  event->accept();
}
示例#13
0
MojErr MojDbKind::configureIndexes(const MojObject& obj, const MojString& locale, MojDbReq& req)
{
	MojLogTrace(s_log);

	// make sure indexes changes count against our usage
	MojErr err = req.curKind(this);
	MojErrCheck(err);

	// add default id index to set
	MojObject idIndex;
	err = idIndex.fromJson(IdIndexJson);
	MojErrCheck(err);
	ObjectSet newIndexObjects;
	err = newIndexObjects.put(idIndex);
	MojErrCheck(err);
	// change back to a set and use contains
	MojSet<MojString> indexNames;
	MojString defaultIdxName;
	err = defaultIdxName.assign(IdIndexName);
	MojErrCheck(err);
	err = indexNames.put(defaultIdxName);
	MojErrCheck(err);
	// add indexes to set to uniquify and order them
	MojObject indexArray;
	if (obj.get(IndexesKey, indexArray)) {
		MojObject::ConstArrayIterator end = indexArray.arrayEnd();
		for (MojObject::ConstArrayIterator i = indexArray.arrayBegin(); i != end; ++i) {
			MojString indexName;
			err = i->getRequired(MojDbIndex::NameKey, indexName);
			MojErrCheck(err);
			err = indexName.toLower();
			MojErrCheck(err);
			if (!indexNames.contains(indexName)) {
				MojObject idx = *i;
				// make sure we keep the lower-cased index name
				err = idx.putString(MojDbIndex::NameKey, indexName);
				MojErrCheck(err);
				err = newIndexObjects.put(idx);
				MojErrCheck(err);
				err = indexNames.put(indexName);
				MojErrCheck(err);
			} else {
				MojErrThrowMsg(MojErrDbInvalidIndexName, _T("db: cannot repeat index name: '%s'"), indexName.data());
			}
		}
	}
	// figure out what to add and what to delete
	ObjectSet toDrop;
	err = m_indexObjects.diff(newIndexObjects, toDrop);
	MojErrCheck(err);
	ObjectSet toAdd;
	err = newIndexObjects.diff(m_indexObjects, toAdd);
	MojErrCheck(err);
	// drop deleted indexes
	IndexVec newIndexes;
	for (IndexVec::ConstIterator i = m_indexes.begin(); i != m_indexes.end(); ++i) {
		if (toDrop.contains((*i)->object())) {
			err = dropIndex(i->get(), req);
			MojErrCheck(err);
		} else {
			err = newIndexes.push(*i);
			MojErrCheck(err);
		}
	}
	// add new indexes
	for (ObjectSet::ConstIterator i = toAdd.begin(); i != toAdd.end(); ++i) {
		// create index
		MojRefCountedPtr<MojDbIndex> index(new MojDbIndex(this, m_kindEngine));
		MojAllocCheck(index.get());
		err = index->fromObject(*i, locale);
		MojErrCheck(err);
		// open index
		err = openIndex(index.get(), req);
		MojErrCheck(err);
		err = newIndexes.push(index);
		MojErrCheck(err);
	}
	// sort indexes by the prop vec so that for indexes that share prop prefixes, the shortest one comes first
	err = newIndexes.sort();
	MojErrCheck(err);
	// update members
	m_indexObjects = newIndexObjects;
	m_indexes = newIndexes;

	return MojErrNone;
}
示例#14
0
void GraphicalReporter::reportPosition(const Quackle::GamePosition &position, Quackle::ComputerPlayer *computerPlayer)
{
	openIndex();

	const QSize pictureSize(500, 500);

	Quackle::GamePosition positionCopy = position;

	{
		QString title;

		if (!position.gameOver())
		{
			title = GraphicalBoard::tr("<h2>%1: Turn %2</h2>").arg(QuackleIO::Util::uvStringToQString(position.currentPlayer().name())).arg(position.turnNumber());
		}
		else
		{
			title = GraphicalBoard::tr("<h2>Game over.</h2>");
		}

		if (m_generateImages)
		{
			QPixmap pixmap;
			positionCopy.resetMoveMade();
			GraphicalBoardFrame::staticDrawPosition(positionCopy, pictureSize, &pixmap);

			QImage image = pixmap.toImage();

			const QString filebasename = QString("%1-%2-position.png").arg(position.turnNumber()).arg(QuackleIO::Util::uvStringToQString(position.currentPlayer().name()));
			const QString filename = makeFilename(filebasename);

			if (image.save(filename, "PNG"))
			{
				m_indexStream << QString("<a href=\"%1\">%2</a>").arg(filebasename).arg(title) << endl;
			}
			else
			{
				QMessageBox::critical(0, GraphicalBoard::tr("Error Writing File - Quacker"), GraphicalBoard::tr("Could not write image %1.").arg(filename));        
			}

			m_indexStream << "<p><img src=\"" << filebasename << "\"></p>" << endl;
		}
		else
		{
			m_indexStream << title;

			const int boardTileSize = position.gameOver()? 45 : 25;
			m_indexStream << QuackleIO::Util::sanitizeUserVisibleLetterString(QuackleIO::Util::uvStringToQString(position.board().htmlBoard(boardTileSize))) << endl;
		}
	}

	const Quackle::PlayerList players(position.endgameAdjustedScores());

	m_indexStream << "<table cellspacing=6>" << endl;
	for (Quackle::PlayerList::const_iterator it = players.begin(); it != players.end(); ++it)
	{
		m_indexStream << "<tr>";

		m_indexStream << "<td>";
		if ((*it) == position.currentPlayer())
			m_indexStream << "&rarr;";
		else
			m_indexStream << "&nbsp;";
		m_indexStream << "</td>";

		m_indexStream
		<< "<td>" << QuackleIO::Util::uvStringToQString((*it).name()) << "</td>"
		<< "<td>" << QuackleIO::Util::sanitizeUserVisibleLetterString(QuackleIO::Util::uvStringToQString((*it).rack().toString())) << "</td>"
		<< "<td>" << (*it).score() << "</td>"
		<< "</tr>"
		<< endl;
	}
	m_indexStream << "</table>" << endl;

	if (computerPlayer && !position.gameOver())
	{
		computerPlayer->setPosition(position);

		if (position.committedMove().isAMove())
			computerPlayer->considerMove(position.committedMove());

		const unsigned int movesToShow = 5;
		Quackle::MoveList moves = computerPlayer->moves(movesToShow);

		if (!moves.contains(position.committedMove()))
		{
			if (moves.size() == movesToShow)
				moves.pop_back();

			moves.push_back(position.committedMove());
		}

		m_indexStream << "<ol>" << endl;
		for (Quackle::MoveList::const_iterator it = moves.begin(); it != moves.end(); ++it)
		{
			QString item;
			switch ((*it).action)
			{
			case Quackle::Move::Place:
			case Quackle::Move::PlaceError:
			{
				if (m_generateImages)
				{
					QPixmap pixmap;

					positionCopy.setMoveMade(*it);
					GraphicalBoardFrame::staticDrawPosition(positionCopy, pictureSize, &pixmap);

					QImage image = pixmap.toImage();

					const QString filebasename = QString("%1-%2-%3-%4.png").arg(position.turnNumber()).arg(QuackleIO::Util::uvStringToQString(position.currentPlayer().name())).arg(QuackleIO::Util::letterStringToQString((*it).prettyTiles())).arg(QuackleIO::Util::uvStringToQString((*it).positionString()));
					const QString filename = makeFilename(filebasename);

					if (image.save(filename, "PNG"))
					{
						item = QString("<a href=\"%1\">%2</a> %3").arg(filebasename);
					}
					else
					{
						QMessageBox::critical(0, GraphicalBoard::tr("Error Writing File - Quacker"), GraphicalBoard::tr("Could not write image %1.").arg(filename));        
					}
				}
				else
				{
					item = "%1 %2";
				}

				item = item.arg(QuackleIO::Util::sanitizeUserVisibleLetterString(QuackleIO::Util::moveToDetailedString(*it))).arg((*it).score);
				break;
			}

			case Quackle::Move::Exchange:
			case Quackle::Move::BlindExchange:
			default:
				item = QuackleIO::Util::moveToDetailedString(*it);
				break;
			}

			if (*it == position.committedMove())
				item += QString(" &nbsp;&larr;");

			if (!item.isEmpty())
				m_indexStream << "<li>" << item << "</li>" << endl;
		}
		m_indexStream << "</ol>" << endl;
	}

	m_indexStream << "\n\n";
}
示例#15
0
void GraphicalReporter::reportHeader(const Quackle::Game &game)
{
	openIndex();
	m_indexStream << kHtmlHeader;
	m_indexStream << QuackleIO::Util::uvStringToQString(game.currentPosition().board().htmlKey());
}