Esempio n. 1
0
void OTOffer::UpdateContents()
{
    const String NOTARY_ID(GetNotaryID()),
        INSTRUMENT_DEFINITION_ID(GetInstrumentDefinitionID()),
        CURRENCY_TYPE_ID(GetCurrencyID());

    // I release this because I'm about to repopulate it.
    m_xmlUnsigned.Release();

    Tag tag("marketOffer");

    tag.add_attribute("version", m_strVersion.Get());

    tag.add_attribute("isSelling", formatBool(!IsBid()));
    tag.add_attribute("notaryID", NOTARY_ID.Get());
    tag.add_attribute("instrumentDefinitionID", INSTRUMENT_DEFINITION_ID.Get());
    tag.add_attribute("currencyTypeID", CURRENCY_TYPE_ID.Get());
    tag.add_attribute("priceLimit", formatLong(GetPriceLimit()));
    tag.add_attribute("totalAssetsOnOffer",
                      formatLong(GetTotalAssetsOnOffer()));
    tag.add_attribute("finishedSoFar", formatLong(GetFinishedSoFar()));
    tag.add_attribute("marketScale", formatLong(GetScale()));
    tag.add_attribute("minimumIncrement", formatLong(GetMinimumIncrement()));
    tag.add_attribute("transactionNum", formatLong(GetTransactionNum()));
    tag.add_attribute("validFrom", formatTimestamp(GetValidFrom()));
    tag.add_attribute("validTo", formatTimestamp(GetValidTo()));

    std::string str_result;
    tag.output(str_result);

    m_xmlUnsigned.Concatenate("%s", str_result.c_str());
}
Esempio n. 2
0
void OTTrade::UpdateContents()
{
    // I release this because I'm about to repopulate it.
    m_xmlUnsigned.Release();

    const String NOTARY_ID(GetNotaryID()), NYM_ID(GetSenderNymID()),
        INSTRUMENT_DEFINITION_ID(GetInstrumentDefinitionID()),
        ASSET_ACCT_ID(GetSenderAcctID()), CURRENCY_TYPE_ID(GetCurrencyID()),
        CURRENCY_ACCT_ID(GetCurrencyAcctID());

    Tag tag("trade");

    tag.add_attribute("version", m_strVersion.Get());
    tag.add_attribute("hasActivated", formatBool(hasTradeActivated_));
    tag.add_attribute("notaryID", NOTARY_ID.Get());
    tag.add_attribute("instrumentDefinitionID", INSTRUMENT_DEFINITION_ID.Get());
    tag.add_attribute("assetAcctID", ASSET_ACCT_ID.Get());
    tag.add_attribute("currencyTypeID", CURRENCY_TYPE_ID.Get());
    tag.add_attribute("currencyAcctID", CURRENCY_ACCT_ID.Get());
    tag.add_attribute("nymID", NYM_ID.Get());
    tag.add_attribute("completedNoTrades", formatInt(tradesAlreadyDone_));
    tag.add_attribute("transactionNum", formatLong(m_lTransactionNum));
    tag.add_attribute("creationDate", formatTimestamp(GetCreationDate()));
    tag.add_attribute("validFrom", formatTimestamp(GetValidFrom()));
    tag.add_attribute("validTo", formatTimestamp(GetValidTo()));

    // There are "closing" transaction numbers, used to CLOSE a transaction.
    // Often where Cron items are involved such as this payment plan, or in
    // baskets,
    // where many asset accounts are involved and require receipts to be closed
    // out.

    for (int32_t i = 0; i < GetCountClosingNumbers(); i++) {
        int64_t closingNumber = GetClosingTransactionNoAt(i);
        OT_ASSERT(closingNumber > 0);
        TagPtr tagClosing(new Tag("closingTransactionNumber"));
        tagClosing->add_attribute("value", formatLong(closingNumber));
        tag.add_tag(tagClosing);
    }

    if (('<' == stopSign_) || ('>' == stopSign_)) {
        TagPtr tagStopOrder(new Tag("stopOrder"));
        tagStopOrder->add_attribute("hasActivated", formatBool(stopActivated_));
        tagStopOrder->add_attribute("sign", formatChar(stopSign_));
        tagStopOrder->add_attribute("price", formatLong(stopPrice_));
        tag.add_tag(tagStopOrder);
    }

    if (marketOffer_.Exists()) {
        OTASCIIArmor ascOffer(marketOffer_);
        tag.add_tag("offer", ascOffer.Get());
    }

    std::string str_result;
    tag.output(str_result);

    m_xmlUnsigned.Concatenate("%s", str_result.c_str());
}
Esempio n. 3
0
void Cheque::UpdateContents()
{
    String INSTRUMENT_DEFINITION_ID(GetInstrumentDefinitionID()),
        NOTARY_ID(GetNotaryID()), SENDER_ACCT_ID(GetSenderAcctID()),
        SENDER_NYM_ID(GetSenderNymID()), RECIPIENT_NYM_ID(GetRecipientNymID()),
        REMITTER_NYM_ID(GetRemitterNymID()),
        REMITTER_ACCT_ID(GetRemitterAcctID());

    std::string from = formatTimestamp(GetValidFrom());
    std::string to = formatTimestamp(GetValidTo());

    // I release this because I'm about to repopulate it.
    m_xmlUnsigned.Release();

    Tag tag("cheque");

    tag.add_attribute("version", m_strVersion.Get());
    tag.add_attribute("amount", formatLong(m_lAmount));
    tag.add_attribute("instrumentDefinitionID", INSTRUMENT_DEFINITION_ID.Get());
    tag.add_attribute("transactionNum", formatLong(GetTransactionNum()));
    tag.add_attribute("notaryID", NOTARY_ID.Get());
    tag.add_attribute("senderAcctID", SENDER_ACCT_ID.Get());
    tag.add_attribute("senderNymID", SENDER_NYM_ID.Get());
    tag.add_attribute("hasRecipient", formatBool(m_bHasRecipient));
    tag.add_attribute("recipientNymID",
                      m_bHasRecipient ? RECIPIENT_NYM_ID.Get() : "");
    tag.add_attribute("hasRemitter", formatBool(m_bHasRemitter));
    tag.add_attribute("remitterNymID",
                      m_bHasRemitter ? REMITTER_NYM_ID.Get() : "");
    tag.add_attribute("remitterAcctID",
                      m_bHasRemitter ? REMITTER_ACCT_ID.Get() : "");

    tag.add_attribute("validFrom", from);
    tag.add_attribute("validTo", to);

    if (m_strMemo.Exists() && m_strMemo.GetLength() > 2) {
        OTASCIIArmor ascMemo(m_strMemo);
        tag.add_tag("memo", ascMemo.Get());
    }

    std::string str_result;
    tag.output(str_result);

    m_xmlUnsigned.Concatenate("%s", str_result.c_str());
}
Esempio n. 4
0
std::ostream& LogProcessor::invalidEntryMsg(const ServerLogEntry &entry)
{
    std::cerr << "Invalid log entry: "
              << formatTimestamp(entry._entry._timestamp)
              << ' ' << entry._entry._userId
              << " at " << entry._clientId
              << ": " << entry._entry._type;
    if (entry._entry._taskId)
    {
        std::cerr << ' ' << *entry._entry._taskId;
    }
    return std::cerr << ": ";
}
// ----------------------------------------------------------------------
void QmvTupleAttribute::load(const QString & data)
{
    original_value = data;

        // Conversions based on datatype
    switch ( dataType() )
    {
        case QmvAttribute::Timestamp:
            if ( data.length() > 0 )
                original_value = formatTimestamp( data );
            break;

        default:
            break;
    }
    
        // conversions based on input method
    switch ( inputMethod() )
    {
        case QmvAttribute::Colour:
                // convert to presentation form #XXXXXX
            bool ok;
            original_value.replace( QRegExp("#"), "").toUInt( &ok, 16);
            if (ok)
            {
                original_value = original_value.rightJustify(8, '0');
                original_value.prepend("#");
            }
            break;

//         case QmvAttribute::List:
//             colour_group.setColor( QColorGroup::Base, QColor("yellow") );
//             setColourGroup(colour_group);
//             break;
            
        default:
            break;
    }

    current_value = original_value;
    QColor alert_colour = alertColour();
    alert  = alert_colour.isValid();
    if ( alert )
    {
        colour_group.setColor( QColorGroup::Base, alert_colour );
        setColourGroup(colour_group);
    } else
        local_colour_group = false;
            
}
Esempio n. 6
0
bool LogProcessor::preliminaryValidate(const ServerLogEntry &entry)
{
    if (entry._entry._userId != _employeeId)
    {
        invalidEntryMsg(entry) << "invalid employee (" << entry._entry._userId
                               << " instead of " << _employeeId << ')' << std::endl;
        return false;
    }
    if (! _employeeIsValid)
    {
        return false;
    }
    if (_previousTimestamp)
    {
        if (*_previousTimestamp > entry._entry._timestamp)
        {
            invalidEntryMsg(entry) << "timestamp not in order (previous timestamp "
                                   << formatTimestamp(*_previousTimestamp) << ')' << std::endl;
            return false;
        }
    }
    _previousTimestamp = entry._entry._timestamp;
    switch (entry._entry._type)
    {
    case LogEntryType_LOGIN:
    case LogEntryType_LOGOUT:
        if (entry._entry._taskId)
        {
            invalidEntryMsg(entry) << " unexpected task id" << std::endl;
            return false;
        }
        break;
    case LogEntryType_TASK_START:
    case LogEntryType_TASK_PAUSE:
    case LogEntryType_TASK_FINISH:
        if (! checkTaskId(entry))
        {
            return false;
        }
        break;
    default:
        invalidEntryMsg(entry) << " invalid type: " << static_cast<int>(entry._entry._type) << std::endl;
        return false;
    }
    return true;
}
Esempio n. 7
0
String formatTimestamp(Date date)
{
    char buffer[30];
    formatTimestamp(date, buffer);
    return String(buffer, 30);
}
void ChatExporterTxt::exportChat(WhatsappChat &chat, const std::string &filename)
{
	std::ofstream file(filename.c_str());

	if (!file)
	{
		throw Exception("could not open chat export file");
	}

	file << chat.getKey();

	if (chat.getSubject().length() > 0)
	{
		file << "; " << chat.getSubject();
	}

	file << std::endl << std::endl;

	std::vector<WhatsappMessage *> &messages = chat.getMessages(true);
	for (std::vector<WhatsappMessage *>::iterator it = messages.begin(); it != messages.end(); ++it)
	{
		WhatsappMessage &message = **it;

		file << formatTimestamp(message.getTimestamp()) << "; ";

		if (message.isFromMe())
		{
			file << "ME: ";
		}
		else
		{
			file << "he: ";
		}

		switch (message.getMediaWhatsappType())
		{
			case MEDIA_WHATSAPP_TEXT:
			{
				file << message.getData();
			} break;
			case MEDIA_WHATSAPP_IMAGE:
			{
				file << "[ Image ]";
			} break;
			case MEDIA_WHATSAPP_AUDIO:
			{
				file << "[ Audio ]";
			} break;
			case MEDIA_WHATSAPP_VIDEO:
			{
				file << "[ Video ]";
			} break;
			case MEDIA_WHATSAPP_CONTACT:
			{
				file << "[ Contact ]";
			} break;
			case MEDIA_WHATSAPP_LOCATION:
			{
				file << "[ Location: " << message.getLatitude() << "; " << message.getLongitude() << " ]";
			} break;
		}

		file << std::endl;
	}
}
Esempio n. 9
0
void LogProcessor::process(ServerLogEntry&& entry)
{
    if (! preliminaryValidate(entry))
    {
        _processed.push_back(entry._id);
        return;
    }

    switch (entry._entry._type)
    {
    case LogEntryType_LOGIN:
        if (_loginEntry)
        {
            invalidEntryMsg(entry) << "login before logout (previous login "
                                   << formatTimestamp(_loginEntry->_entry._timestamp)
                                   << " at " << _loginEntry->_clientId << ')' << std::endl;
            _processed.push_back(_loginEntry->_id);
        }
        _loginEntry = std::move(entry);
        break;
    case LogEntryType_LOGOUT:
        if (! _loginEntry)
        {
            invalidEntryMsg(entry) << "logout before login" << std::endl;
        }
        else
        {
            if (_loginEntry->_clientId != entry._clientId)
            {
                          invalidEntryMsg(entry) << "login at different station: "
                                                 << formatTimestamp(_loginEntry->_entry._timestamp)
                                                 << " at " << _loginEntry->_clientId << std::endl;
            }
            _processed.push_back(_loginEntry->_id);
            _loginEntry = boost::none;
        }
        _processed.push_back(entry._id);
        break;
    case LogEntryType_TASK_START:
    {
        int taskId = *entry._entry._taskId;
        auto workStartEntry = _workStartEntrys.find(taskId);
        if (workStartEntry != _workStartEntrys.end())
        {
            ServerLogEntry& prevEntry = workStartEntry->second;
            invalidEntryMsg(entry) << "work start before work stop (previous start "
                                   << formatTimestamp(prevEntry._entry._timestamp)
                                   << " at " << prevEntry._clientId << ')' << std::endl;
            _processed.push_back(prevEntry._id);
            prevEntry = std::move(entry);
        }
        else
        {
            auto res = _workStartEntrys.insert(std::make_pair(taskId, std::move(entry)));
            assert(res.second);
        }
        break;
    }
    case LogEntryType_TASK_PAUSE:
    {
        int taskId = *entry._entry._taskId;
        auto workStartEntry = _workStartEntrys.find(taskId);
        if (workStartEntry != _workStartEntrys.end())
        {
            const ServerLogEntry& prevEntry = workStartEntry->second;
            if (prevEntry._clientId != entry._clientId)
            {
                invalidEntryMsg(entry) << "work start at different station: "
                                       << formatTimestamp(prevEntry._entry._timestamp)
                                       << " at " << prevEntry._clientId << std::endl;
            }
            else
            {
                auto assignment = _assignments.find(taskId);
                assignment->second._timeSpent += entry._entry._timestamp - prevEntry._entry._timestamp;
            }
            _processed.push_back(prevEntry._id);
            _processed.push_back(entry._id);
            _workStartEntrys.erase(workStartEntry);
        }
        else
        {
            invalidEntryMsg(entry) << "work pause before work start" << std::endl;
            _processed.push_back(entry._id);
        }
        break;
    }
    case LogEntryType_TASK_FINISH:
    {
        int taskId = *entry._entry._taskId;
        auto workStartEntry = _workStartEntrys.find(taskId);
        if (workStartEntry != _workStartEntrys.end())
        {
            const ServerLogEntry& prevEntry = workStartEntry->second;
            if (prevEntry._clientId != entry._clientId)
            {
                invalidEntryMsg(entry) << "work start at different station (start "
                                       << formatTimestamp(prevEntry._entry._timestamp)
                                       << " at " << prevEntry._clientId << std::endl;
            }
            else
            {
                auto assignment = _assignments.find(taskId);
                assignment->second._timeSpent += entry._entry._timestamp - prevEntry._entry._timestamp;
                assignment->second._finished = true;
            }
            _processed.push_back(prevEntry._id);
            _processed.push_back(entry._id);
            _workStartEntrys.erase(workStartEntry);
        }
        else
        {
            invalidEntryMsg(entry) << "work finish before work start" << std::endl;
            _processed.push_back(entry._id);
        }
        break;
    }
    }
}
Esempio n. 10
0
bool PersistenceService::saveGame(uint slotID, const Common::String &screenshotFilename) {
	// FIXME: This code is a hack which bypasses the savefile API,
	// and should eventually be removed.

	// Überprüfen, ob die Slot-ID zulässig ist.
	if (slotID >= SLOT_COUNT) {
		error("Tried to save to an invalid slot (%d). Only slot ids form 0 to %d are allowed.", slotID, SLOT_COUNT - 1);
		return false;
	}

	// Dateinamen erzeugen.
	Common::String filename = generateSavegameFilename(slotID);

	// Spielstanddatei öffnen und die Headerdaten schreiben.
	Common::SaveFileManager *sfm = g_system->getSavefileManager();
	Common::OutSaveFile *file = sfm->openForSaving(filename);

	file->writeString(FILE_MARKER);
	file->writeByte(0);
	file->writeString(VERSIONID);
	file->writeByte(0);

	char buf[20];
	snprintf(buf, 20, "%d", VERSIONNUM);
	file->writeString(buf);
	file->writeByte(0);

	TimeDate dt;
	g_system->getTimeAndDate(dt);
	file->writeString(formatTimestamp(dt));
	file->writeByte(0);

	if (file->err()) {
		error("Unable to write header data to savegame file \"%s\".", filename.c_str());
	}

	// Alle notwendigen Module persistieren.
	OutputPersistenceBlock writer;
	bool success = true;
	success &= Kernel::getInstance()->getScript()->persist(writer);
	success &= RegionRegistry::instance().persist(writer);
	success &= Kernel::getInstance()->getGfx()->persist(writer);
	success &= Kernel::getInstance()->getSfx()->persist(writer);
	success &= Kernel::getInstance()->getInput()->persist(writer);
	if (!success) {
		error("Unable to persist modules for savegame file \"%s\".", filename.c_str());
	}

	// Write the save game data uncompressed, since the final saved game will be
	// compressed anyway.
	char sBuffer[10];
	snprintf(sBuffer, 10, "%u", writer.getDataSize());
	file->writeString(sBuffer);
	file->writeByte(0);
	snprintf(sBuffer, 10, "%u", writer.getDataSize());
	file->writeString(sBuffer);
	file->writeByte(0);
	file->write(writer.getData(), writer.getDataSize());

	// Get the screenshot
	Common::SeekableReadStream *thumbnail = Kernel::getInstance()->getGfx()->getThumbnail();

	if (thumbnail) {
		byte *buffer = new byte[FILE_COPY_BUFFER_SIZE];
		thumbnail->seek(0, SEEK_SET);
		while (!thumbnail->eos()) {
			int bytesRead = thumbnail->read(&buffer[0], FILE_COPY_BUFFER_SIZE);
			file->write(&buffer[0], bytesRead);
		}

		delete[] buffer;
	} else {
		warning("The screenshot file \"%s\" does not exist. Savegame is written without a screenshot.", filename.c_str());
	}

	file->finalize();
	delete file;

	// Savegameinformationen für diesen Slot aktualisieren.
	_impl->readSlotSavegameInformation(slotID);

	// Empty the cache, to remove old thumbnails
	Kernel::getInstance()->getResourceManager()->emptyThumbnailCache();

	// Erfolg signalisieren.
	return true;
}
Esempio n. 11
0
tstring ValueFormatter::format(const tstring& server,
							   const tstring& topic,
							   const tstring& item,
							   const tstring& value) const
{
	typedef tstring::const_iterator citer;

	tstring result;

	result.reserve(m_valueFormat.length() + item.length() + value.length());

	for (citer it = m_valueFormat.begin(); it != m_valueFormat.end(); ++it)
	{
		if (*it == TXT('%'))
		{
			citer variableIt = it+1;

			if (variableIt == m_valueFormat.end())
				throw Core::ParseException(Core::fmt(TXT("Invalid output format: '%s'"), m_valueFormat.c_str()));

			const tchar variable = *variableIt;

			if (variable == TXT('%'))
			{
				result += TXT('%');
			}
			else if (variable == TXT('v'))
			{
				if (m_trimValue)
					result += Core::trimCopy(value);
				else
					result += value;
			}
			else if (variable == TXT('s'))
			{
				result += server;
			}
			else if (variable == TXT('t'))
			{
				result += topic;
			}
			else if (variable == TXT('i'))
			{
				result += item;
			}
			else if (variable == TXT('d'))
			{
				result += formatTimestamp(m_dateFormat, m_timeFormat);
			}
			else
			{
				throw Core::ParseException(Core::fmt(TXT("Invalid output variable: '%%%c'"), variable));
			}

			++it;
		}
		else
		{
			result += *it;
		}
	}

	return result;
}
ChatControlMessageFrame::ChatControlMessageFrame(ChatControlMessage *message, int width, int color, HFONT dateFont)
    : message(message), width(width), color(color), height(0), dateFont(dateFont)
{
    wcharDate = strtowstr(formatTimestamp(message->getMessage().getTimestamp()));
}
Esempio n. 13
0
std::string ChatExporterHtml::buildMessages(WhatsappChat &chat, std::set<int> &usedEmoticons)
{
	std::stringstream output;

	std::vector<WhatsappMessage *> &messages = chat.getMessages(true);
	for (std::vector<WhatsappMessage *>::iterator it = messages.begin(); it != messages.end(); ++it)
	{
		WhatsappMessage &message = **it;

		output << "<div class=\"message ";

		if (message.isFromMe())
		{
			output << "outgoing_message";
		}
		else
		{
			output << "incoming_message";
		}

		output << "\"><div class=\"text\">";

		switch (message.getMediaWhatsappType())
		{
			case MEDIA_WHATSAPP_TEXT:
			{
				output << "<span>" << convertMessageToHtml(message, usedEmoticons) << "</span>";
			} break;
			case MEDIA_WHATSAPP_IMAGE:
			{
				if (message.getRawDataSize() > 0 && message.getRawData() != NULL)
				{
					output << "<div><img src=\"data:image/jpeg;base64," << base64_encode(message.getRawData(), message.getRawDataSize()) << "\"></div>" << std::endl;
				}
			} break;
			case MEDIA_WHATSAPP_AUDIO:
			{
				output << "<span>[ " << formatAudio(message) << " ]</span>";
			} break;
			case MEDIA_WHATSAPP_VIDEO:
			{
				if (message.getRawDataSize() > 0 && message.getRawData() != NULL)
				{
					output << "<div><img src=\"data:image/jpeg;base64," << base64_encode(message.getRawData(), message.getRawDataSize()) << "\"></div>" << std::endl;
				}
				output << "<span>[ Video ]</span>";
			} break;
			case MEDIA_WHATSAPP_CONTACT:
			{
				output << "<span>[ Contact ]</span>";
			} break;
			case MEDIA_WHATSAPP_LOCATION:
			{
				output << "<span>[ Location: " << message.getLatitude() << "; " << message.getLongitude() << " ]</span>";
			} break;
		}

		output << "</div><div class=\"timestamp\"><span>" << formatTimestamp(message.getTimestamp()) << "</span></div></div>" << std::endl;
	}

	return output.str();
}
Esempio n. 14
0
void ClientConnection::handleCommand(const std::string& line)
{
    if (boost::iequals(line, "RETRIEVE TASKS"))
    {
        auto& query = findTasksForLoginQ();
        query.execute(_userId);
        std::unique_ptr<ClientTask> task;
        while (query.next(task))
        {
            _stream.writeLine(concatln("TASK ", task->_id, " TITLE ", quoteString(task->_title), " SPENT ", toSeconds(task->_timeSpent)));
            for (const auto& line : task->_description)
            {
                _stream.writeLine(concatln(line));
            }
            _stream.writeLine("\n");
        }
        _stream.writeLine("END TASKS\n");
    }
    else if (boost::iequals(line, "LOG UPLOAD"))
    {
        auto& lastEntryTimeQ = findLastLogEntryTimeForClientQ();
        lastEntryTimeQ.execute(_clientId);
        boost::optional<Timestamp> lastEntryTime;
        bool res = lastEntryTimeQ.next(lastEntryTime);
        assert(res);
        assert(! lastEntryTimeQ.next(lastEntryTime));
        if (lastEntryTime)
        {
            _stream.writeLine(concatln("LAST ENTRY AT ", formatTimestamp(*lastEntryTime)));
        }
        else
        {
            _stream.writeLine("NO ENTRYS\n");
        }
        int taskId;
        std::set<std::string> employeeIds;
        bool loop = true;
        while (loop)
        {
            auto line = _stream.readLine();
            LogEntry entry;
            if (parse(line, TimestampToken(entry._timestamp), " ", BareStringToken(entry._userId), " LOGIN"))
            {
                entry._type = LogEntryType_LOGIN;
            }
            else if (parse(line, TimestampToken(entry._timestamp), " ", BareStringToken(entry._userId), " LOGOUT"))
            {
                entry._type = LogEntryType_LOGOUT;
            }
            else if (parse(line, TimestampToken(entry._timestamp), " ", BareStringToken(entry._userId),
                           " TASK ", IntToken(taskId), " START"))
            {
                entry._type = LogEntryType_TASK_START;
                entry._taskId = taskId;
            }
            else if (parse(line, TimestampToken(entry._timestamp), " ", BareStringToken(entry._userId),
                           " TASK ", IntToken(taskId), " PAUSE"))
            {
                entry._type = LogEntryType_TASK_PAUSE;
                entry._taskId = taskId;
            }
            else if (parse(line, TimestampToken(entry._timestamp), " ", BareStringToken(entry._userId),
                           " TASK ", IntToken(taskId), " FINISH"))
            {
                entry._type = LogEntryType_TASK_FINISH;
                entry._taskId = taskId;
            }
            else if (boost::iequals(line, "END LOG"))
            {
                loop = false;
            }
            else
            {
                throw ProtocolError("Invalid log entry", line);
            }

            if (loop)
            {
                employeeIds.insert(entry._userId);
                insertLogEntry(entry);
            }
        }
        for (const auto& employeeId : employeeIds)
        {
            processLogs(employeeId);
        }
        emit tasksStatusChanged();
    }
    else
    {
        throw ProtocolError("Invalid command", line);
    }
}