Creating an address
To create an Edgeware mnemonic and keypair locally, follow the
steps below. If you would rather create a keypair online,
visit the
key generator.
-
Install rust and cargo here
-
Execute the following script once cargo is installed
cargo install --force --git https://github.com/paritytech/substrate subkey
-
Create an account by running the following command
subkey generate
Save the output somewhere safe, it contains your secret mnemonic
to generate future keypairs.
It should look like the following:
Phrase `welcome draft actor now search injury enhance cigar misery move december essay` is account:
Seed: 0xa2cc1ebe0a6cb0ae78311cd37156aac988e61c312d73cafe357cc2f1fd069e09
Public key (hex): 0xb2d1bda2d363cf25a26a9fb34ea314dc8981e378ca4797c52117f65731602826
Address (SS58): 5G7AgnBBNvdDYRVvcCYz95pMjGtS3ouWaq23Dcqe6rDjDuh7
-
Copy the Public key (hex) for use on the Edgeware Lockdrop homepage.
-
Note that if you intend to be a validator when the network
launches, you will need to generate three public keys, two
of which should be sr25519 keys as above:
subkey generate
One key should be an ed25519 key:
subkey generate -e
Unlocking
To trigger unlocking of ETH stored in a user lockdrop
contract, wait until the locktime has expired, and send any
transaction to the user lockdrop contract's address.
-
After sending a lock transaction, any ETH that was sent to
the master lockdrop contract will be
transferred into a user lockdrop contract.
-
You can find the user lockdrop contract by going to your
lock transaction on Etherscan, and looking for the contract
created by that transaction:
-
Create a transaction sending 0 ETH to that contract address,
from any address. As long as the lock has expired, funds
will be automatically released to the address that originally
locked them.
Testing on Ropsten
-
The lockdrop contract deployed on Ropsten
at
0x111ee804560787E0bFC1898ed79DAe24F2457a04
has shorter locktimes of 15min, 30min, and 60min, instead of
3, 6, and 12 months respectively.
‹ Back home


We have paired you up with a mentor to advise you with a focus on what focus you listed as the area you needed advice in. Your match is under the match tab and you will see information about them including their major, minor, etc. You are also provided their email address if you want to contact them to set up a meeting. We hope you enjoy this service and get all your questions answered. Remember your mentor is here to help and signed up to answer your questions. Don't be nervous or afraid to ask anything. That's what we're here for!


Since JakeMUD is a lightweight MMORPG MUD, the data is even fewer than MMORPGs in gaming industry. Thus, we have to scale up our result to be visible. Our recommended solution indeed reduce some bandwidth when some characters AFK. But the differences are relatively small.
TCP/UDP in MMORPGs is all about trade-off:
Between - Infrastructure requirement vs. TCP’s reliability
Between - Bandwidth vs. Speed
Between - UDP unreliability vs. TCP retransmission
But what's the future? Feel free to send us email about your thoughts!
1. Disable Nagle’s Algorithm
2. Reduce server bandwidth on previous project JakeMUD (TCP-based MUD)
- Movement detection
- Send out a resume sequence number to client
- Multiple streaming channels to process messages - Move, Attack, Talk
- Move, Attack switch to UDP, Talk stick with TCP
- Switch back to TCP with resume number from client
We will think more about firewall traversal in our final report. Also, we will dig into the measurement for TCP/UDP comparison, our recommended solution in JakeMUD.
Presentation In ECS from 11:00 am - 12:00 pm!
Retransmission timeout - ping increases significantly if packet dropped
Big header - we have Nagle's algorithm! But you want bandwidth or less latency?
Internet Speed
One of the major reason that game developer use TCP instead of UDP is that the internet speed nowadays become faster and affordable. The internet speed is fast enough to minimize TCP packet dropping. Therefore, the game developers tend to use TCP as their transport protocol as it is more reliable than UDP.
Congestion Control
The second reason of choosing TCP over UDP is TCP provide congestion control. What we found one of the characteristic of MMORPG network traffic is the actual size of game packet payload is small compared to other online games. You may ask: since TCP may consume more bandwidth than UDP, why still sending small packet with TCP?
The answer is Nagle’s Algorithm. It combines few more small packets to send to save bandwidth. UDP header doesn’t have window size, if the whole game uses UDP, it may occupy your whole bandwidth. So sometimes we feel our game is slow, it most likely nothing to do with network speed, just because the application buffer limits the traffic!
Cheat Detection
In the old days, cheat detection relied on server side has evolved to client side now. The day when internet speed was relatively slow, sometimes game server need to take the responsibility of cheat detection. For example, to prevent cheating software to clear all fog of war, server need to send back confirmation of explored fog of war, UDP do the job better on this. If TCP would be applied to respond explored fog, players can notice the inconsistency because of TCP’s ACK delay. But today, most real-time cheating detection can be done locally by the software itself, the need of relying UDP on cheat detection has gone
UDP is more efficient with smaller packet size. But we have three main reasons to use TCP.
They are - Internet speed, Congestion control, and Anti-cheat software!
We will choose the following three MMORPGs as our study subject since they are more typical.
EverQuest (1999) - UDP
World of Warcraft (2004) - TCP
Blade and Soul (2012) - TCP
We will show you our three main reasons choosing TCP over UDP in MMORPG, and propose a possible solution to improve some functions.
Our paper will focus on the trade-off of using TCP/UDP in MMORPG, what the reasons behind this are, and we will propose a possible hybrid solution.
We haven't started this step yet. But once UDP is implemented, we will analyze the packet trace. A survey from players might be conducted.
We are tying to modify JakeMUD to transmit UDP (except talk messages). And see how well the performance is in term of reliability, consistency, and latency.
We will start to test JakeMUD's TCP traffic divided into three types of messages - move, attack, and talk.
JakeMUD is a lightweight multiplayers game, and it shares the characteristic of allowing multiple players to connect to the service, and provide a game experience wherein players type and send commands which allow their player character to interact with the game environment. Both user input and the game's responses are presented in a textual format describing the action, or the action's results. JakeMUD applies a structured, centralized game server connected on an overlay network via calling port number. JakeMUD mainly uses TCP as its transport protocol which is different from main stream MUD games since JakeMUD doesn't emphasize on real-time in-game consistency.
During our study, CS (Counter Strick) and many other FPS games, RTS games are using UDP since it requires non-stop updating the status and location of a player. Yet, in recent years, game industry has started to combine MMORPG to FPS or MMORPG to RTS. LOL is an example combining MMORPG and RTS.
So we choose GTA 5 ONLINE to study what transport protocol that FPS-MMORPG would use nowadays. Our guess is pure TCP. Let's find out!
To summaried what we have found so far, almost all MMORPG games are now using TCP! Yet not all game packets need the function and characteristics of TCP. Move messages don't require reliability of TCP. Especially when a player is detected AFK (away-from-keyboard), UDP could save the network bandwidth. Also, we guess move messages don't need to be ordered since players move simultaneously don't affect each other most likely. Attack messages may require reliability depends on the drop rate of game packets. Only talk messages need reliability as well as be ordered strictly which requires TCP no doubt.
What we found is the packet generation rate of MMORPG is pretty low compared to FPS and RTS games. This is a reason why choosing TCP over UDP since there are fewer data to transmit. Instead, reliability is much more important in this sense.
Diablo II, WOW, EverQuest
Fantasy Westward Journey, Blade And Soul, LOL
EverQuest is one of the MMORPG still using UDP. EverQuest is a 3D fantasy-themed massively multiplayer online role-playing game (MMORPG) released on March 16, 1999. It was the second commercially viable MMORPG to be released, after Ultima Online, and the first commercially successful MMORPG to employ a three-dimensional game engine. Since this is the first generation 3D MMORPG developed released in 1999, why could a UDP game works in an era when network was relatively slow? Any trade-off chossing UDP to transmit in 1999?
As we also suspect the reason why MMORPG games use TCP more than anytime ever, is because network infrastructure has been improving, does it mean classic RPG don't use TCP? We will test one RPG game with multiplayer festure and a MMORPG game.
We choose Diablo II as our RPG sample and Ever Quest as our MMORPG sample. Diablo II is an action role-playing hack and slash video game developed by Blizzard North and published by Blizzard Entertainment in 2000.
Back to a real MMORPG game. We are going to look into World of Warcraft (WoW). WoW is a massively multiplayer online role-playing game (MMORPG) released in 2004 by Blizzard Entertainment.
We know it mainly uses TCP. Interestingly, when we play WoW during our packet capturing, we found that characters can move and stand on a same spot rather than players can box out each other in LOL. We suspect that makes players don't feel the in-game delay casued by TCP since the server doesn't need to predict players' potential paths, which is impossible without any delay.
League of Legends (abbreviated LoL) is a multiplayer online battle arena video game developed and published by Riot Games for Microsoft Windows and macOS. So technically speaking, it is a 3D, third-person multiplayer online battle arena (MOBA) game rather than a MMORPG. Only a small amount of players in each room comparied to MMORPG games.
So why would we bother to investgate LOL? If we categorize all game packets into move, attack, and talk, LOL is mainly consisted with move and attack. We want to see how much traffic will move and attack create. And more IMPORTANTLY, if it use TCP to move, how does the game predict one player boxes out another without delay. Or, is it inevitable without delay?
Blade And Soul (블레이드 앤 소울) is a Korean fantasy martial-arts MMORPG game developed by NCSOFT (Team Bloodlust). On September 13, 2012, NCSOFT announced that Blade And Soul would release in Western territories, which eventually happened on January 19, 2016.
4.8 hours traffic was recorded for our research.
 It was released for the Microsoft Windows platform in December 2001. The game is the most popular online game in China as of May 2007 by peak concurrent users (PCU), with a peak count of 1.5 million.
We have captured the traffic playing this game. Since it is a turn-based MMORPG game, we hope it uses UDP for main trasmission. The result will be analyzed soon.
Midterm presentation prepare and due
Populated Project Proposal
Update information onto Group website. Discussion on Project Proposal improvement
Group meeting discuss on the research and gather information. And look for appropriate simulation tool
Initial website layout ready
Assigned two articles for EACH group member to read over the reading break
Group meeting discuss on received feedback, and Group meeting discuss on Website layout
Final editing for Project Proposal
Initial draft for Project Proposal - discuss about transport layer based on different gaming server architectures
Group decided to focus on TCP/UDP in gaming industry
Group individual research for possible topic


Channel¶
Warning
‘winner’ is considered highly unstable.
-
class
ch.
ChBulk_v2
(Stations, Users, Param)¶ This is the main API class for interfacing with implemented models.
-
ChBulk_v2
(Stations, Users, Param)¶ See
SonohiChannel
for the structure ofParam
-
setupChannelUL
(Stations, Users, varargin)¶ Setup channel given the UL schedule, e.g. the association to simulate when traversed.
Parameters: - Stations (
enb.EvolvedNodeB
) – - Users (
ue.UserEquipment
) –
- Stations (
-
traverse
(Stations, Users, chtype, varargin)¶ This method applies the channel properties to the receiver modules. The recieved waveform and meaningful physical parameters are written to the receiver module depending on the channel type selected. Two options exist.
Parameters: - Stations (
enb.EvolvedNodeB
) – Station objects with a transmitter and receiver module. - Users (
ue.UserEquipment
) – UE objects with a transmitter and receiver module - chtype (str) – the receptive Rx module is configured using ‘downlink’ or ‘uplink’, if ‘downlink’ Users.Rx modules are used to store the final waveforms and physical parameters.
- varargin – (‘fieldType’,’field’) can be given to bypass fading and interference, ‘full is default’
Stations
needs the following fields:Stations.Users
: needed for getting link association between stations and usersStations.NCellID
: Identifier to link associationStations.Tx
: Transmitter moduleStations.Rx
: Receiver module
Users
needs the following fields:Users.NCellID
: Identifier to link associationUsers.ENodeBID
: Identifier to link associationUsers.Tx
: Transmitter moduleUsers.Rx
: Receiver module
- Stations (
-
-
class
ch.
SonohiChannel
(Stations, Users, Param)¶ This is the base coordinator class for the physical channels.
Currently supported models: [
winner
,eHATA
,ITU1546
,3GPP38901
,B2B
]Warning
‘uplink’ is currently only available in B2B mode.
The constructor requires the following options:
Input Param: Parameter struct containing the following: Param.channel.modeDL: (str) Channel model used in downlink. e.g. ‘winner’ Param.channel.modeUL: (str) Channel model used in uplink. e.g. ‘B2B’ Param.channel.region: (str) Region of channel. This changes based on the channel model as the mapping and definition is considered different. See each model for the configuration of this, e.g. ch.SONOHImodels
Param.Seed: (int) Base seed for the channel Param.channel.enableFading: (bool) Enable/disable fading Param.channel.enableInterference: (bool) Enable/disable interference Param.enableShadowing: (bool) Enable/disable spartial correlated shadowing, currently only supported using 3GPP38901
Param.LOSMethod: (str) ‘fresnel’ or ‘3GPP38901-probability’, See ch.SonohiChannel.isLinkLOS()
for more info.Param.buildings: (optional) Needed for ‘fresnel’ LOSMethod, Structure containing footprints of buildings, given by (x0, y0, x1, y1) coordinates. -
isLinkLOS
(Station, User, draw)¶ Check if link between txPos and rxPos is LOS using one of two methods
SonohiChannel.LOSMethod
:fresnel
1st Fresnel zone and the building footprint.SonohiChannel.LOSMethod
:3GPP38901-probability
Uses probability given table 7.4.2-1 of 3GPP TR 38.901. Seech.SONOHImodels.3GPP38901.sonohi3GPP38901.LOSprobability()
for more the implementation.
Parameters: - Station (
enb.EvolvedNodeB
) – NeedStations.Position
andStations.DlFreq
. - User (
ue.UserEquipment
) – NeedUser.Position
- draw (bool) – Draws fresnel zone and elevation profile.
Returns: LOS (bool) indicating LOS
Returns: (optional) probability is returned if
3GPP38901-probability
is assigned
-
Examples¶
A simple example can be found in ch/examples/SimpleExample.m
clear all
close all
load('SimulationParameters.mat');
Param.numMacro = 1;
Param.numMicro = 0;
Param.numPico = 0;
Param.numUsers = 1;
Param.channel.region = 'Suburban';
Param.channel.enableShadowing = false;
Param.channel.modeDL = 'ITU1546';
if Param.draw
Param = createLayoutPlot(Param);
Param = createPHYplot(Param);
end
% Create Stations and Users
[Station, Param] = createBaseStations(Param);
User = createUsers(Param);
% Create Channel scenario
Channel = ChBulk_v2(Station, User, Param);
Station.Users = struct('UeId', User.NCellID, 'CQI', -1, 'RSSI', -1);
Station.ScheduleDL(1,1).UeId = User.NCellID;
User.ENodeBID = Station.NCellID;
% A full LTE frame is stored in Tx.Frame which can be used to debug and
% test.
Station.Tx.Waveform = Station.Tx.Frame;
Station.Tx.WaveformInfo =Station.Tx.FrameInfo;
Station.Tx.ReGrid = Station.Tx.FrameGrid;
% Traverse channel
[~, User] = Channel.traverse(Station,User,'downlink');
% Get offset
User.Rx.Offset = lteDLFrameOffset(Station, User.Rx.Waveform);
% Apply offset
User.Rx.Waveform = User.Rx.Waveform(1+User.Rx.Offset:end);
% UE reference measurements
User.Rx = User.Rx.referenceMeasurements(Station);


Login Name
Delete
add item
Update
Home
Search item
choose a colour
Blue
Green
Brown
Yellow
White
Black
choose a material
Wool
Silk
Cotton
Cashmere
Polyester
choose a
sneakers
Sandles
Heels
choose a colour
choose a colour


[gecode-users] How to set an arbitrary RandomGenerator for randomized branching?!?
Martin Mann
mmann at informatik.uni-freiburg.de
Mon May 18 19:01:39 CEST 2009
Alright, what is my scenario:
I have a stochastic simulation e.g. a Markov chain. Within this
simulation, for each step x_i a CSP is formulated and I would like to
get a random solution r. This solution r is accepted based on some
probability. Thus, I can stay at x_i (x_(i+1)=x_i) or proceed to r
(x_(i+1)=r).
So I have two "areas" where random numbers are produced: (1) the Markov
chain and (2) the randomized branching within Gecode.
Now I would like to have ONE pseudo random number generator (RNG) used
for both to ensure that I have reproducable results...
One possible hack is the following:
- assume RNG_M for the markov chain and RNG_G for gecode internals.
- for each step I set the seed of RNG_G via a random number drawn from RNG_M
- I use RNG_M for the Markov chain step check
Would be an option, but it would ease the problem a lot if one could
directly use the same RNG for both or not?
Another point about arbitrary RNGs is about statistics. I am working in
a field were e.g. physics care a lot about the random number
distributions and statistics a pseudo random number generator gives.
Therefore, these people like to set up their favorite RNG they trust
most to give low-biased stochastic simulations.
In the above solution, the RNG_M can be defined freely, the RNG_G not.
That's why I was asking. :) It's not about speed or space, more about
application.
But so long the above solution will do or has to be sufficient.
Thanks,
Martin
Javier Andrés Mena Zapata schrieb:
> Hi,
>
> Just curiosity... Do you prefer RNG speed, RNG space, general speed or
> general space?
>
> Cheers,
>
> On Mon, May 18, 2009 at 2:55 AM, Mikael Zayenz Lagerkvist
> <zayenz at gmail.com>wrote:
>
>> Hi,
>>
>> Currently it is not possible to exchange the random number generator.
>> Furthermore, the implementation uses properties of the random number
>> generator that would most probably compromise efficiency if they were
>> abstracted away (for example, the state is limited to a single
>> unsigned int as seed). If you want to use your own random number
>> generator, I would suggest writing your own subclasses of ViewSelBase
>> and ValSelbase similar to ViewSelRnd and ValRnd.
>>
>> For curiosity, what is the reason that you want to change the random
>> number generator used?
>>
>> Cheers,
>> Mikael
>>
>> On Sat, May 16, 2009 at 12:37 AM, Martin Mann
>> <mmann at informatik.uni-freiburg.de> wrote:
>>> Hi everybody,
>>>
>>> I digged a bit into the Gecode source about the randomized branching
>>> supported since version 3.
>>>
>>> In line 124 in gecode/support/random.hpp I found the definition of
>>> RandomGenerator internally used in the view selection:
>>>
>>>
>> http://www.gecode.org/doc-latest/reference/group__FuncSupport.html#g02fe942f90a57a25639f09960dab4459
>>> As given there, it is just a typedef onto the
>>> LinearCongruentialGenerator provided by Gecode but I would like to set
>>> up my own random number generator...
>>>
>>> Is there a possibility to support user defined generators? e.g. in
>>> coming versions?
>>>
>>> If not available right now, maybe you like the following suggestion:
>>>
>>> A possibility would be a super class 'RNG' that has to be implemented by
>>> every generator plus a kind of factory class 'RNF' with static members
>> only.
>>> The RNF would be a wrapper around the current RNG instance to use
>>> (stored in a static internal member). Thus, all Gecode internals that
>>> need a random number use a static interface of RNF instead of some RNG
>>> instance members. So the library gets independent of the concrete RNG
>>> used and you get the possibility to register a user defined RNG within
>>> the RNF. Per default the RNF can use the linear congruential generator
>>> provided. The static interface and data member would avoid annoying
>>> copies of RNGs all around and won't complicate your Gecode
>> internals/source.
>>>
>>> Just a suggestion... if it is already possible just ignore and please
>>> let me know how to do with the current Gecode version. :)
>>>
>>>
>>> Have a nice weekend,
>>>
>>> Martin
>>>
>>>
>>> _______________________________________________
>>> Gecode users mailing list
>>> users at gecode.org
>>> https://www.gecode.org/mailman/listinfo/gecode-users
>>>
>>
>>
>> --
>> Mikael Zayenz Lagerkvist, http://www.ict.kth.se/~zayenz/<http://www.ict.kth.se/%7Ezayenz/>
>>
>> _______________________________________________
>> Gecode users mailing list
>> users at gecode.org
>> https://www.gecode.org/mailman/listinfo/gecode-users
>>
>
>
>
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> Gecode users mailing list
> users at gecode.org
> https://www.gecode.org/mailman/listinfo/gecode-users
--
Martin Mann, Dipl. Bioinf.
Bioinformatics - Inst. of Computer Science
Albert-Ludwigs-University Freiburg
Tel: ++49-761-203-8259
Fax: ++49-761-203-7462
http://www.bioinf.uni-freiburg.de/~mmann/
More information about the gecode-users
mailing list


About me
Brief
- Full name : Georgy Buranov
- Job title : Senior Lead Software Developer
- Area of interest : Accepting interesting offers. Got huge technical experience(Go, Rails, C++), can also manage teams (technical decisions, time estimations, people management)
- Homepage : http://gburanov.me
- LinkedIn profile : http://www.linkedin.com/in/gburanov
- Stackoverflow profile : https://careers.stackoverflow.com/gburanov
- Github profile : https://github.com/gburanov
Contact information
- Phone : +49 1523 663 2480
- Email<EMAIL_ADDRESS>- Website : http://gburanov.me
- Country : Germany
- Address : Lindauer Allee 15, 13407 Berlin
- Birthdate : 22.08.1981
- Nationality : Russian. Got German working permit (unlimited)
- Open for reallocation : Yes (if the offer is REALLY interesting)
Summary
Summary
I worked as a C++ software developer for a very long time, but now I switched to Go and/or Ruby/ROR.
I also use Python mostly for data science related things.
I got experience managing teams (3-7 people). Technical decisions, Time estimations, People management.
I like microservice approach and try to use it if it is possible
I do care about infrastructure and familiar with Docker, Kubernetes, Chef, Ansible…
I think microservice architecture need proper monitoring and I can do it (Influx, Kapacitor, Prometheus, Alertmanager, etc..)
I think data and how you organize it is more important than code in many scenarios
Knowledge of agile methodologies (Scrum, Kanban)
Learning new things is my passion
Working experience in two countries with different cultures - Russia and Germany
Ability to create, understand and implement design specifications. Ability to solve complicated problems.
Ability to quickly understand new code and start contributing without significant delay.
Working with huge amount of legacy code.
Open-source experience (Chromium browser, GRUB2, etc…). Ability both to understand existing design and to contribute to the open-source (sometimes by finding golden middle)
Ability to work in team. Wide experience in using collaborative software; repositories, bug tracking systems, review systems.
Ability to automate routine jobs.
Wide use of automated testing (unit tests, functional tests, integration tests, acceptance tests). Unit testing of legacy code.
Career History
Mar 2018 - Now
Senior Software Developer (Go)
Berlin, DE
Responsibilties:
Senior Backend Developer, Team Lead
Head of Dev Oncall
Leading various projects around bidding, DS, etc
Guiding new people
Solving problems
Knowledge:
High Scale - 1 Million Requests per minute
Data Engineering to allow DS to build and train new data models
Feb 2017 - Mar 2018
Lead Senior Developer (Go, Ruby)
Berlin, DE
Responsibilties:
Lead for the iDSP project
Monitoring project for the microservice architecture - increased the stability of the system a lot (Influx, Kapacitor, Prometheus)
CI integration for many microservices (Docker, Amazon Beanstack, Mesos, Chronos, etc)
Increased the test coverage of Go projects a lot
integration of Data Science team with Developers
Knowledge:
Shorten the loop when direct communication with stakeholders
Importance of correct monitoring
How to merge mathematics and engineers =)
Jul 2016 - Feb 2017
Senior Developer (Ruby, Go)
Berlin, DE
Responsibilties:
Lots of communication with Bangalore office
Using Go and Ruby to developer various services for company
Monitoring project for the microservice architecture - increased the stability of the system a lot
CI integration for many microservices (Docker, Amazon Beanstack, Mesos, Chronos, etc)
integration of several external partners in the system
Knowledge:
New language (Go) in production (used to be a hobby)
Lots of new Devops knowledge
Oct 2015 - Jul 2016
Senior Ruby Developer
Berlin, DE
Responsibilties:
Mobile Api, Affiliate Api
Supporting mobile API projects (fixing bugs, extending API)
Affiliate API project - start from scratch. Finished successfully.
CI with Docker deploy
Statistics/Monitoring (Kibana/ELK)
Knowledge:
Getting familiar with AWS stack
Trying to do micro-service approach
Testing approaches for microservices
May 2012 - Oct 2015
Backend Software developer, Team manager
Russia, Germany
Responsibilties:
Working on projects backend alone from beginning to the very end
Projects maintaining
Details (as well as source code) are available upon request
Knowledge:
Ruby
Rails
Automated Testing (rspec, capybara)
Tons of gems
Nov 2014 - Oct 2015
Software Engineer, Browser Project
Tettnang, DE
Responsibilties:
Browser based on Chromium
Starting new project completely from scratch
Creating project environment (build tools, scripts, documentation)
Knowledge:
Working with really HUGE amount of legacy code
Ability to inject your code in correct place in quite small amount of time
Advanced GIT (merging to constantly developing open-source and back)
Sep 2013 - Nov 2014
Unix and Mac software developer
Tettnang, DE
Responsibilties:
Avira Rescue System (Ubuntu based system for rescue booting and restoring your OS)
OsX version of Avira products
Responsible for maintaining (and writing new code) for kernel extension (driver)
Knowledge:
Agile software development approach
Legacy code unit tests coverage
New code unit test coverage
Working with GIT
Aug 2008 - May 2013
Software Developer, Senior Software Developer, UEFI project
Moscow, RUS
Responsibilties:
Investigation of new booting mechanism (UEFI)
Fix “Bootability restore” module for UEFI
UEFI loader
Understanding, documentation and coding of UEFI boot mechanism for both Windows and Linux
Multiplatform solution
Knowledge:
Ability to work with a lot of documentation
System shipped succesfully
Aug 2008 - May 2013
Software Developer, Senior Software Developer, Bootability detect/restore
Moscow, RUS
Responsibilties:
Detecting/restoring different OSes bootability (different Linux versions, Windows)
Bootability investigation (all levels, from MBR to kernel loading)
refactoring + maintaining code
Multiplatform solution
Aug 2008 - May 2013
Software Developer, Senior Software Developer, Fdisk project
Moscow, RUS
Responsibilties:
Fdisk library has about the same functionality as Linux fdisk. It is the base core library of all Acronis products
Support + new functionality for fdisk library
Code documentation
Maintenance of LDM, MBR, GPT libraries
Implementing Storage spaces support (new Windows 8/2012 feature)
Multiplatform solution
Aug 2008 - May 2013
Software Developer, Scheduler project
Moscow, RUS
Responsibilties:
Multiplatform scheduling service for starting tasks (backups, verification, etc.) at special timepoint
Multiplatform development&debugging (Windows, Linux, Mac)
Module for task scheduling, based on cron (Linux), LauchAgent (Mac) and Windows Service (Windows)
Jan 2007 - Sep 2008
Software Developer, Reuters project
Responsibilties:
Reuters got a huge platform for dealing with different finance aspects Reuters 3000 Xtra.
We were responsible for Calculators plugin. It was calculating market values using predefined templates.
Every day connecting to Paris office
Huge amount of code supporting
Working with bank software (more security and code check)
Invention of unit testing (JUnit library)
May 2005 – July 2006
Software Developer, Recovery Manager for Exchange
Responsibilties:
Designing Object-Oriented library for Jet Blue Engine.
CRUD API for working with Exchange store (Read, Write, Update, Delete)
Layer over the library – for using with managed code.
Reading messages from store without Exchange Server (No-SQL Jet Blue Database)
Knowledge:
-Studying design patterns -OO libraries from scratch.
Dec 2003 – May 2005
Software Developer, Auditor project, IIS collection module
Responsibilties:
Developing GUI using Qt
DB Storage modification (SQL, C#)
Integration with other modules using COM
Collection IIS information
Improvement of special language for collection (in short, C++ code generation language, based on XML, XSLT)
Knowledge:
My first job as a software developer.
Learning STL, Boost, Qt.
Working with SVN, bug tracking system.
Logrus
Jul 2002 – August 2003
QA
Responsibilties:
Manual (70%) and Automated (30%) testing.
Logrus was responsible for localization of huge software projects, like Microsoft Windows and Lotus Notes
Knowledge:
Working for not full time in a big company I gained knowledge of different processes going on in big companies
MEPHI 26 department
Sep 2002 – Feb 2004
Software developer
Responsibilties:
Payment module for car detection system. It was used for some time on several car stations
Languages
Languages
- Russian : Native
- English : Upper Intermediate
- German : Intermediate (B 2)
- Spanish : Beginner (A2.1)
Language certificates
- English : IELTS certificate 7.0 total


Moving on from the browser era, the next big thing was search. The internet browser was the perfect vehicle that could make finding information online easy, but the problem was that there was no existing “search engine” at the time. This was solved in the early 200s by Silicon Valley natives Jerry Yang and David Filo. Trying to win a Stanford fantasy basketball league, they stumbled upon the idea which would then lead them to create a guide to the internet. This directory that they created, immediately grew in popularity- Yahoo was then born.
Search was incredibly popular at this time, but still no one had figured out how to monetize this feature. Advertising was the clear path for revenue, but this was a highly risky proposition at the time as there was a stigma around selling space on their page for ads. Nonetheless, yahoo went ahead and agreed to display ads, and their user count kept growing. This was the first time that monetization had successfully been pulled off on the web.
Yahoo was not the only player at this time however. Excite was another startup with one fundamental difference. Rather than manually entering and creating this directory of sites, excite used software to crawl the internet and search for results. These platforms started to fiercely compete and used a tit for tat strategy. As soon as one company came out with a unique feature, the other would immediately follow and develop their version of that feature and launch it as well.
This led to another problem; these companies which started out as essentially search engines evolved to something much more. But in the journey they forgot about their original intent which was the search feature itself. This is where google came into play. They were able to deduce the fact that the most clicked on results were the closest to the search that they were looking for. Link counting became the core of Google’s success. Most importantly, google brought back the idea and popularity of search again.
After multiple large investments, google had pressure to find a good business model. Up till now they had revolutionized the search engine and undeniably created a unique product, but they had not yet figured out a way to monetize this. They did not want to simply splatter their sites with ads that did not make sense like Yahoo and Excite. This is when Google turned to a model from a smaller company called overture where they would cater ads to a specific person based on keywords. It used these keywords as data points- essentially acting as a market research tool. Google was able to take this concept and incorporate it into their search engine and it was an immediate success.
Before taking their company public in 2004 there was a lot of skepticism because this was the period right after the Dot com bubble. However, this logic proved to be wrong. Immediately after their shares started trading they shot up and never looked back. Since then google has poured its enormous resources into various projects. As google expanded more and more they came head to head with more competitors.


class SidechainConfig
Describes all sidechain's configs
<init> |
Describes all sidechain's configs SidechainConfig() |
btcAssetId |
var btcAssetId: String? |
echoGenAddressMethod |
var echoGenAddressMethod: Method? |
erc20WithdrawTopic |
var erc20WithdrawTopic: String? |
ethAssetId |
var ethAssetId: String? |
ethCommitteeUpdateMethod |
var ethCommitteeUpdateMethod: Method? |
ethCommitteeUpdateTopic |
var ethCommitteeUpdateTopic: String? |
ethContractAddress |
var ethContractAddress: String? |
ethDepositTopic |
var ethDepositTopic: String? |
ethGenerateAddressTopic |
var ethGenerateAddressTopic: String? |
ethUpdateAddressMethod |
var ethUpdateAddressMethod: Method? |
ethWithdrawMethod |
var ethWithdrawMethod: Method? |
ethWithdrawTopic |
var ethWithdrawTopic: String? |
gasPrice |
var gasPrice: String? |
waitingETHBlocks |
var waitingETHBlocks: String? |


Abstract
This document has some overall analysis of time patterns obtained by the surveys, that is, when weekday trips take place in mteropolitan areas. These are disaggregated by travel mode, motive, and socioeconomic data.
First, we take a look at the distribution of trip starting and ending time for the six cities:
Montevideo shows a very smooth curve, while Buenos Aires and Sao Paulo show much more abrupt peaks. Santiago and Bogota start showing a high degree of noise (high frequency peaks), a pattern exacerbated in Mexico city. This shows a substantial difference in the time patterns of its citizens, but also in the urban morphology: more centers and a very redundant transit system yields much more variability in the trip starting times.
We observe the distributions for trips start and trip ending times to be very similar, owing to the fact most trips take an hour or less to be performed:
Hence we look only at trip start times. We observe the distinct distribution of Bogota, with a larger share of longer trips.
Both graphs do not show large differences between female and male schedules. In some cities, the middle peaks seem different for each group; for some cases the earlier peak seems more female-dominant, and the midday/evening peak more male-dominant, yet nothing overwhelming. The following plot shows the relative participation of each gender across time of day:
The younger group shows clearly the 3 peaks of the overall distribution, as well as the other working age groups. From age 50 onwards, it becomes more diffuse, and ages over 70 show a majority of participants in the middle peak.
Observe walking as the main participant of mid-day peaks. The use of taxi as a plateau between working hours.
There are very clear patterns according to motive, not identical by city.
There is an interesting pronunciation of the mid-day peak in lower income groups.
Post processing within the IDB tried to identified patterns for trips that were outside the limits of the metropolitan area. These were distinguished as originating outside, or bound for outside, of the city limits. Sao Pailo and Buenos Aires were excluded from this analysis due to the lack of geographical coordinates in the survey responses.
The city of Montevideo shows and equal distribution of these two groups with respect to the total of the trips. This may be owed to the city size. In the other three cases, trips with destination outside of the city limits are skewed towards an earlier time,


--- layout: post title: Character sketch date: '2013-11-28T07:30:00+01:00' categories: - Character - Sketches picture_url: https://film-Storyboards.tumblr.com/post/68360754998/character-sketch ---
Character sketch.


// TPTElements for
C++ /
Lua /
C
// References for
The Lua API /
OPSv1
ops-reference.html
==================
A walkthrough on the OPS save format TPT uses.
Make sure to refer to the document actually detailing the save format - the
source code!
Link at time of writing
Index
=====
1.
Bytes of OPS1
2.
The BSON save format
3. Various subformats
3.1
The wallmap subformat for walls
3.1.1
The fan-map subformat for fan data
3.2
The parts-map and parts-position subformat for particles
3.2.1
The particle properties saved
3.3
The sign-map subformat for signs
3.4
The soap-link subformat for soap bubbles
1. Bytes of OPS1
----------------
Okay so a save file usually looks like a jumbled mess. That's because it's not
saved as valid text, as it represents most of its data in binary. Binary that
Notepad(++) or any other conventional text editor tries to use as character
codes.
There are editing programs called hex editors however, which don't even
bother with the character codes and display the bits themselves. The most
convenient and common way said bits are displayed is hexadecimal (two letters
for a whole byte? sign me up!). You can read more on hexadecimal
here.
Sometimes very rarely hexadecimal numbers are represented with a leading or
trailing character sequence to make it clear that they are in hexadecimal.
0x60 and 60h are two common notations, where both tell us that the number 60 is
in fact a hexadecimal number.
So let's open up an average save file with a hex editor, what'll we see?
4f 50 53 31
- this is simply the text 'OPS1' in ASCII, which kind of
identifies which file it is for the computer.
58
- This keeps track of which major version the save was created in.
This one is TPT version 0x58 (convert that to decimal, it's 88!)
You'll get an error "Save from newer version", if this number is bigger
than the SAVE_VERSION constant in your game code (or simply put, if the save
is from a newer version than you have, you get an error!)
04
- the cell width of this save - this tells TPT how wide your wall blocks,
and the pressure, velocity, newtonian gravity, and ambient heat grids are.
99
- how many wall blocks go on a horizontal line
(you can calculate it by dividing the game width (WIDTH) with the cell width,
which in normal TPT is 612 / 4 = 153. 153 is represented in hexadecimal
as 99.)
60
- how many wall blocks go on a vertical line.
(you can calculate it by dividing the game height with the cell width, which
in normal TPT is 384 / 4 = 96. 96 represented in hexadecimal is 60.)
57 cc 0a 00
- the next four bytes represent how big the rest of the file is.
The size is represented as a regular C integer, except for the fact
that the first byte is the last, the second byte is the
second-to-last in the file, and so on.
Below you can see the snippet of code that makes the first 12 bytes what they
are.
outputData[0] = 'O';
outputData[1] = 'P';
outputData[2] = 'S';
outputData[3] = '1';
outputData[4] = SAVE_VERSION;
outputData[5] = CELL;
outputData[6] = blockW;
outputData[7] = blockH;
outputData[8] = finalDataLen;
outputData[9] = finalDataLen >> 8;
outputData[10] = finalDataLen >> 16;
outputData[11] = finalDataLen >> 24;
2. The BSON save format
-----------------------
The rest of the file is compressed using bzip2, which you can easily decompress
and explore. It's still not much good however, since the data inside /itself/ is
also written using a binary format.
You can in fact simply decompress the file using your favorite archive manager
(that supports bzip2 data!), by stripping off the first 12 bytes (don't simply
turn them to nulls!), and re-saving it as a ".bz2" file. Extracting that file
will yield you the BSON data inside!
The binary format is called
BSON - a portmanteau of
JSON (Javascript Object
Notation) and binary. It's tinier and strictly typed, but those also make it a
bit more tedious to parse.
The structure of data in BSON will look kind of like this, approximating with
JSON syntax:
{
"origin": {
// The major version number of the game that the save was made in.
// MAJOR_VERSION -- looks like 81
"majorVersion": integer,
// The minor version number (bugfixes, etc) of the game.
// MINOR_VERSION -- looks like 0
"minorVersion": integer,
// The build index, which is basically like a never-ending counter that
// goes up every time TPT is compiled on the official build server.
// BUILD_NUM -- looks like 272
"buildNum": integer,
// The snapshot ID, which is basically a Unix timestamp of when the
// snapshot was compiled. It's rarely used, but you might still encounter it
// in the wild.
// SNAPSHOT_ID -- looks like<PHONE_NUMBER>
"snapshotId": integer,
// Release type, which is both an OS and an architecture identifier, all
// in one!
// IDENT_PLATFORM -- looks like "WIN32" or "LIN64"
"releaseType": string,
// Build type, which tells you if the game was built on legacy or
// SSE1/2/3 TPT.
// IDENT_BUILD -- looks like "SSE3" or "LEGACY"
"builtType": string
},
// Is water equalization turned on?
"waterEEnabled": boolean,
// Is heat simulation turned /off/?
"legacyEnable": boolean,
// Is Newtonian Gravity turned on?
"gravityEnable": boolean,
// Is Ambient Heat turned on?
"aheat_enable": boolean,
// Was the game paused when saving?
"paused": boolean,
// Which Gravity Mode to use?
// Vertical : 0 (the default)
// Off: 1
// Radial: 2
"gravityMode": integer,
// Which Air Mode to use?
// All on : 0 (the default)
// No Pressure : 1
// No Velocity : 2
// No Pressure & Velocity : 3
// No Update : 4
"airMode": integer,
// Not yet used:
// "leftSelectedElement": integer,
// "rightSelectedElement": integer,
// "activeMenu": integer,
// All of the next properties are totally optional. They might appear,
// and usually they do, but they also might not.
// All of them use some kind of freaky format so bear with me and scroll down
// to find the details for a particular format.
// Particles and all about them that's saved
"parts": binary (user-defined format!),
// How many particles are in a specific position in the parts array
"partsPos": binary (user-defined format!),
// Wall grid
"wallMap": binary (user-defined format!),
// A special wall grid for fan-walls
"fanMap": binary (user-defined format!),
// Even more special grid for soap connection points.
// I'll detail some parts, but make sure to check out the source code.
"soapLinks": binary (user-defined format!),
// Signs
// Signs are the only easy format, I'll detail them here:
"signs": [
// (each sign adds an object into this array!)
{
"text": string,
"justification": integer,
"x": integer,
"y": integer
}
]
// Palette of element IDs:
// not saved with current format saves.
// Might be in the future.
"element name": element ID,
...
}
From here on in, I really suggest you look at the source code as well as read
the description. I'm not always correct as I've learned, so you might find some
quirks or details that I've left out or missed entirely.
The wall map format
-------------------
//Read wall and fan data
if(wallData)
{
j = 0;
if(blockW * blockH > wallDataLen)
{
fprintf(stderr, "Not enough wall data\n");
goto fail;
}
for(x = 0; x < blockW; x++)
{
for(y = 0; y < blockH; y++)
{
if (wallData[y*blockW+x])
blockMap[blockY+y][blockX+x] = wallData[y*blockW+x];
if (blockMap[y][x]==O_WL_WALLELEC)
blockMap[y][x]=WL_WALLELEC;
if (blockMap[y][x]==O_WL_EWALL)
blockMap[y][x]=WL_EWALL;
if (blockMap[y][x]==O_WL_DETECT)
blockMap[y][x]=WL_DETECT;
if (blockMap[y][x]==O_WL_STREAM)
blockMap[y][x]=WL_STREAM;
if (blockMap[y][x]==O_WL_FAN||blockMap[y][x]==O_WL_FANHELPER)
blockMap[y][x]=WL_FAN;
if (blockMap[y][x]==O_WL_ALLOWLIQUID)
blockMap[y][x]=WL_ALLOWLIQUID;
if (blockMap[y][x]==O_WL_DESTROYALL)
blockMap[y][x]=WL_DESTROYALL;
if (blockMap[y][x]==O_WL_ERASE)
blockMap[y][x]=WL_ERASE;
if (blockMap[y][x]==O_WL_WALL)
blockMap[y][x]=WL_WALL;
if (blockMap[y][x]==O_WL_ALLOWAIR)
blockMap[y][x]=WL_ALLOWAIR;
if (blockMap[y][x]==O_WL_ALLOWSOLID)
blockMap[y][x]=WL_ALLOWSOLID;
if (blockMap[y][x]==O_WL_ALLOWALLELEC)
blockMap[y][x]=WL_ALLOWALLELEC;
if (blockMap[y][x]==O_WL_EHOLE)
blockMap[y][x]=WL_EHOLE;
if (blockMap[y][x]==O_WL_ALLOWGAS)
blockMap[y][x]=WL_ALLOWGAS;
if (blockMap[y][x]==O_WL_GRAV)
blockMap[y][x]=WL_GRAV;
if (blockMap[y][x]==O_WL_ALLOWENERGY)
blockMap[y][x]=WL_ALLOWENERGY;
if (blockMap[y][x] == WL_FAN && fanData)
{
if(j+1 >= fanDataLen)
{
fprintf(stderr, "Not enough fan data\n");
}
fanVelX[blockY+y][blockX+x] = (fanData[j++]-127.0f)/64.0f;
fanVelY[blockY+y][blockX+x] = (fanData[j++]-127.0f)/64.0f;
}
if (blockMap[y][x] < 0 || blockMap[y][x] >= UI_WALLCOUNT)
blockMap[y][x] = 0;
}
}
}
So, the size of this tremendous data structure is usually how many walls could
fit into a save. You can use in-the-code constants and calculate it like this:
(XRES*YRES)/CELL
With official TPT, this value comes right at 58752 elements.
First things first, convert the very linear data structure that walls are kept
in into a more two-dimensional grid. Code like the below should suffice:
for (x = 0; x < blockW, x++)
for (y = 0; y < blockH, y++)
blockmap [x] [y] = wallData [y * blockW + x];
Second, you'll have to convert every wall that uses old wall values (O_WL_*) into
newer wall values.
Special case though: if the wall type is O_WL_FANHELPER, the new wall you should
use instead of it is WL_FAN.
if (blockMap[y][x]==O_WL_FAN||blockMap[y][x]==O_WL_FANHELPER)
blockMap[y][x]=WL_FAN;
The fan-map subformat
~~~~~~~~~~~~~~~~~~~~~
The fan-map looks kinda like this:
[x velocity for fan #1, y velocity for fan #1,
x velocity for fan #2, y velocity for fan #2,
...]
The actual velocity is calculated from the stored value
like this:
actual = (stored-127.0f)/64.0f
Keep a 'fan data array pointer' (I'll use j) at where you are in the array currently.
If the wall type is WL_FAN and the fan data array exists (read in earlier), then
check if j is in range of the fan data array. If it is not, copy over fan
velocity data kinda like this:
fanVelX[blockY+y][blockX+x] = (fanData[j++]-127.0f)/64.0f; // j = 1
fanVelY[blockY+y][blockX+x] = (fanData[j++]-127.0f)/64.0f; // j = 2 etc
// before the double loop:
j = 0;
if (blockMap[y][x] == WL_FAN && fanData)
{
if(j+1 >= fanDataLen)
{
fprintf(stderr, "Not enough fan data\n");
}
fanVelX[blockY+y][blockX+x] = (fanData[j++]-127.0f)/64.0f;
fanVelY[blockY+y][blockX+x] = (fanData[j++]-127.0f)/64.0f;
}
Some data may be left out which your code will have to tolerate and replace
with 'none-walls' of index 0.
The particle map format
-----------------------
Now for the real can of worms, the particle map! Try and follow through this,
it's kind of a wild ride.
//Read particle data
if(partsData && partsPosData)
{
int newIndex = 0, fieldDescriptor, tempTemp;
int posCount, posTotal, partsPosDataIndex = 0;
int saved_x, saved_y;
if(fullW * fullH * 3 > partsPosDataLen)
{
fprintf(stderr, "Not enough particle position data\n");
goto fail;
}
partsSimIndex = (unsigned int*)calloc(NPART, sizeof(unsigned));
partsCount = 0;
i = 0;
newIndex = 0;
for (saved_y=0; saved_y<fullH; saved_y++)
{
for (saved_x=0; saved_x<fullW; saved_x++)
{
//Read total number of particles at this position
posTotal = 0;
posTotal |= partsPosData[partsPosDataIndex++]<<16;
posTotal |= partsPosData[partsPosDataIndex++]<<8;
posTotal |= partsPosData[partsPosDataIndex++];
//Put the next posTotal particles at this position
for (posCount=0; posCount<posTotal; posCount++)
{
particlesCount = newIndex+1;
if(newIndex>=NPART)
{
goto fail;
}
//i+3 because we have 4 bytes of required fields (type (1), descriptor (2), temp (1))
if (i+3 >= partsDataLen)
goto fail;
x = saved_x + fullX;
y = saved_y + fullY;
fieldDescriptor = partsData[i+1];
fieldDescriptor |= partsData[i+2] << 8;
if(x >= fullW || x < 0 || y >= fullH || y < 0)
{
fprintf(stderr, "Out of range [%d]: %d %d, [%d, %d], [%d, %d]\n", i, x, y, (unsigned)partsData[i+1], (unsigned)partsData[i+2], (unsigned)partsData[i+3], (unsigned)partsData[i+4]);
goto fail;
}
if(partsData[i] >= PT_NUM)
partsData[i] = PT_DMND; //Replace all invalid elements with diamond
if(newIndex < 0 || newIndex >= NPART)
goto fail;
//Store partsptr index+1 for this saved particle index (0 means not loaded)
partsSimIndex[partsCount++] = newIndex+1;
//Clear the particle, ready for our new properties
memset(&(particles[newIndex]), 0, sizeof(Particle));
//Required fields
particles[newIndex].type = partsData[i];
particles[newIndex].x = x;
particles[newIndex].y = y;
i+=3;
//Read temp
if(fieldDescriptor & 0x01)
{
//Full 16bit int
tempTemp = partsData[i++];
tempTemp |= (((unsigned)partsData[i++]) << 8);
particles[newIndex].temp = tempTemp;
}
else
{
//1 Byte room temp offset
tempTemp = (char)partsData[i++];
particles[newIndex].temp = tempTemp+294.15f;
}
//Read life
if(fieldDescriptor & 0x02)
{
if(i >= partsDataLen) goto fail;
particles[newIndex].life = partsData[i++];
//Read 2nd byte
if(fieldDescriptor & 0x04)
{
if(i >= partsDataLen) goto fail;
particles[newIndex].life |= (((unsigned)partsData[i++]) << 8);
}
}
//Read tmp
if(fieldDescriptor & 0x08)
{
if(i >= partsDataLen) goto fail;
particles[newIndex].tmp = partsData[i++];
//Read 2nd byte
if(fieldDescriptor & 0x10)
{
if(i >= partsDataLen) goto fail;
particles[newIndex].tmp |= (((unsigned)partsData[i++]) << 8);
//Read 3rd and 4th bytes
if(fieldDescriptor & 0x1000)
{
if(i+1 >= partsDataLen) goto fail;
particles[newIndex].tmp |= (((unsigned)partsData[i++]) << 24);
particles[newIndex].tmp |= (((unsigned)partsData[i++]) << 16);
}
}
}
//Read ctype
if(fieldDescriptor & 0x20)
{
if(i >= partsDataLen) goto fail;
particles[newIndex].ctype = partsData[i++];
//Read additional bytes
if(fieldDescriptor & 0x200)
{
if(i+2 >= partsDataLen) goto fail;
particles[newIndex].ctype |= (((unsigned)partsData[i++]) << 24);
particles[newIndex].ctype |= (((unsigned)partsData[i++]) << 16);
particles[newIndex].ctype |= (((unsigned)partsData[i++]) << 8);
}
}
//Read dcolour
if(fieldDescriptor & 0x40)
{
if(i+3 >= partsDataLen) goto fail;
particles[newIndex].dcolour = (((unsigned)partsData[i++]) << 24);
particles[newIndex].dcolour |= (((unsigned)partsData[i++]) << 16);
particles[newIndex].dcolour |= (((unsigned)partsData[i++]) << 8);
particles[newIndex].dcolour |= ((unsigned)partsData[i++]);
}
//Read vx
if(fieldDescriptor & 0x80)
{
if(i >= partsDataLen) goto fail;
particles[newIndex].vx = (partsData[i++]-127.0f)/16.0f;
}
//Read vy
if(fieldDescriptor & 0x100)
{
if(i >= partsDataLen) goto fail;
particles[newIndex].vy = (partsData[i++]-127.0f)/16.0f;
}
//Read tmp2
if(fieldDescriptor & 0x400)
{
if(i >= partsDataLen) goto fail;
particles[newIndex].tmp2 = partsData[i++];
if(fieldDescriptor & 0x800)
{
if(i >= partsDataLen) goto fail;
particles[newIndex].tmp2 |= (((unsigned)partsData[i++]) << 8);
}
}
//Read pavg
if(fieldDescriptor & 0x2000)
{
if(i+3 >= partsDataLen) goto fail;
int pavg;
pavg = partsData[i++];
pavg |= (((unsigned)partsData[i++]) << 8);
particles[newIndex].pavg[0] = (float)pavg;
pavg = partsData[i++];
pavg |= (((unsigned)partsData[i++]) << 8);
particles[newIndex].pavg[1] = (float)pavg;
}
//Particle specific parsing:
switch(particles[newIndex].type)
{
case PT_SOAP:
//Clear soap links, links will be added back in if soapLinkData is present
particles[newIndex].ctype &= ~6;
break;
case PT_BOMB:
if (particles[newIndex].tmp!=0 && savedVersion < 81)
{
particles[newIndex].type = PT_EMBR;
particles[newIndex].ctype = 0;
if (particles[newIndex].tmp==1)
particles[newIndex].tmp = 0;
}
break;
case PT_DUST:
if (particles[newIndex].life>0 && savedVersion < 81)
{
particles[newIndex].type = PT_EMBR;
particles[newIndex].ctype = (particles[newIndex].tmp2<<16) | (particles[newIndex].tmp<<8) | particles[newIndex].ctype;
particles[newIndex].tmp = 1;
}
break;
case PT_FIRW:
if (particles[newIndex].tmp>=2 && savedVersion < 81)
{
int caddress = restrict_flt(restrict_flt((float)(particles[newIndex].tmp-4), 0.0f, 200.0f)*3, 0.0f, (200.0f*3)-3);
particles[newIndex].type = PT_EMBR;
particles[newIndex].tmp = 1;
particles[newIndex].ctype = (((unsigned char)(firw_data[caddress]))<<16) | (((unsigned char)(firw_data[caddress+1]))<<8) | ((unsigned char)(firw_data[caddress+2]));
}
break;
case PT_PSTN:
if (savedVersion < 87 && particles[newIndex].ctype)
particles[newIndex].life = 1;
break;
case PT_STKM:
case PT_STKM2:
case PT_FIGH:
if (savedVersion < 88 && particles[newIndex].ctype == OLD_SPC_AIR)
particles[newIndex].ctype = SPC_AIR;
break;
case PT_FILT:
if (savedVersion < 89)
{
if (particles[newIndex].tmp<0 || particles[newIndex].tmp>3)
particles[newIndex].tmp = 6;
particles[newIndex].ctype = 0;
}
break;
case PT_QRTZ:
case PT_PQRT:
if (savedVersion < 89)
{
particles[newIndex].tmp2 = particles[newIndex].tmp;
particles[newIndex].tmp = particles[newIndex].ctype;
particles[newIndex].ctype = 0;
}
break;
}
//note: PSv was used in version 77.0 and every version before, add something in PSv too if the element is that old
newIndex++;
}
}
}
if (soapLinkData)
{
int soapLinkDataPos = 0;
for (i=0; i<partsCount; i++)
{
if (partsSimIndex[i] && particles[partsSimIndex[i]-1].type == PT_SOAP)
{
// Get the index of the particle forward linked from this one, if present in the save data
int linkedIndex = 0;
if (soapLinkDataPos+3 > soapLinkDataLen) break;
linkedIndex |= soapLinkData[soapLinkDataPos++]<<16;
linkedIndex |= soapLinkData[soapLinkDataPos++]<<8;
linkedIndex |= soapLinkData[soapLinkDataPos++];
// All indexes in soapLinkData and partsSimIndex have 1 added to them (0 means not saved/loaded)
if (!linkedIndex || linkedIndex-1>=partsCount || !partsSimIndex[linkedIndex-1])
continue;
linkedIndex = partsSimIndex[linkedIndex-1]-1;
newIndex = partsSimIndex[i]-1;
//Attach the two particles
particles[newIndex].ctype |= 2;
particles[newIndex].tmp = linkedIndex;
particles[linkedIndex].ctype |= 4;
particles[linkedIndex].tmp2 = newIndex;
}
}
}
}
To read it we'll need both partsData and partsPosData to exist in the save
with enough data in partsPosData for every particle * 3.
Size of partsPosData: fullW * fullH * 3
partsPosData is basically how many particles are under this exact position,
starting from {0,0} going towards {x:384, y:0} and then to {x:0,y:1} and onward.
The full number is consisted of three bytes which are or'ed together conveniently:
[0x00, 0x00, 0x05,
0x00, 0x00, 0x00,
0x00, 0x00, 0x04,
...]
//Read total number of particles at this position
posTotal = 0;
posTotal |= partsPosData[partsPosDataIndex++] << 16;
posTotal |= partsPosData[partsPosDataIndex++] << 8;
posTotal |= partsPosData[partsPosDataIndex++];
For every particle in a given position x, y, there's posTotal particles we
have to create. Loop from 0 to posTotal to go over every particle in the
given position.
Now comes the fun part.
We have 4 bytes of required fields:
type (byte 0), descriptor (byte 2), temp (byte 1)
... and a whole lot of optional fields.
The array looks kinda like this:
[type, temp, descriptor, [optionals],
type, temp, descriptor, [optionals],
...]
Now back to the implementation.
Your particle's position will be determined by adding the stage's size in that
dimension to the current position in the loop. Please look at the code, this will
make more sense to you.
Saved particle properties
~~~~~~~~~~~~~~~~~~~~~~~~~
First off, to check if the descriptor field has a given byte set, you have to
binary-AND the descriptor field with the given bit.
e.g If the descriptor field has a 0x02 bit set
bool has_it = descriptor_field & 0x02 != 0;
If the descriptor field has a 0x01 bit set, then your temp value will have an
extra byte appended to its front as the optional byte #4 and it'll be saved
as an absolute temperature value.
[type, temp, descriptor, x-temp]
endresult = temp | x-temp<<8;
Else the temp value will be used as an offset from 294.15 K.
endresult = temp + 294.15f;
If the descriptor field has a 0x02 bit set then your next byte will be the life
value. If the descriptor field also has a 0x04 bit set then the life value will
have two bytes instead of one and the second byte will have to be attached to
the first one.
[type, temp, descriptor[, ...], life[, x-life]]
life = life | x-life << 8
If the descriptor field has a 0x08 bit set then your next byte will be the tmp
value. If the descriptor field also has a 0x10 bit set then the tmp value will
have two bytes instead of one and the second byte will have to be attached to
the first one. If the descriptor field also has a 0x1000 bit set then the tmp
value will also have two more extra bytes set.
[type, temp, descriptor[, ...], tmp [, x-tmp[, x-x-tmp, x-x-x-tmp]]]
tmp = tmp | x-tmp << 8 [ | x-x-tmp << 24 | x-x-x-tmp < < 16];
If the descriptor field has a 0x20 bit set then your next byte will be the ctype
value. If the descriptor field also has a 0x200 bit set then the ctype value will
have four bytes instead of one and the second byte will have to be attached to
the first one.
[type, temp, descriptor[, ...], ctype[, x-ctype, x-x-ctype, x-x-x-ctype]]
ctype = ctype [ | x-ctype << 24 | x-x-ctype < < 16 | x-x-x-ctype << 8 ];
If the descriptor field has a 0x40 bit set then your next four bytes will be the
dcolour value. If the descriptor field also has a 0x200 bit set then the dcolour
value will have four bytes instead of one and the second byte will have to be
attached to the first one.
[type, temp, descriptor[, ...], dcolour, x-dcolour, x-x-dcolour, x-x-x-dcolour]
dcolour = dcolour << 24 | x-dcolour << 16 | x-x-dcolour << 8 | x-x-x-dcolour ];
vx and vy are nice and simple, one byte each. vx is indicated by the descriptor
having a 0x80 byte and vy by the 0x100 byte.
[type, temp, descriptor[, ...], vx_, vy_]
vx = (vx_-127.0f)/16.0f;
vy = (vy_-127.0f)/16.0f;
The tmp2 field gets wonky again: 0x400 identifies it and 0x800 turns on the
additional byte.
[type, temp, descriptor[, ...], tmp[, x-tmp]]
tmp = tmp | x-tmp << 8
Then there's pavg which I am not sure what it does. Identified by 0x2000,
two bytes per array index, two array indices.
[type, temp, descriptor[, ...], pavg0, x-pavg0, pavg1, x-pavg1]
pavg[0] = pavg0 | x-pavg0 << 8
pavg[1] = pavg1 | x-pavg1 << 8
Now for the fun particle-specific stuff.
switch(particles[newIndex].type)
{
case PT_SOAP:
//Clear soap links, links will be added back in if soapLinkData is present
particles[newIndex].ctype &= ~6;
break;
case PT_BOMB:
if (particles[newIndex].tmp!=0 && savedVersion < 81)
{
particles[newIndex].type = PT_EMBR;
particles[newIndex].ctype = 0;
if (particles[newIndex].tmp==1)
particles[newIndex].tmp = 0;
}
break;
case PT_DUST:
if (particles[newIndex].life>0 && savedVersion < 81)
{
particles[newIndex].type = PT_EMBR;
particles[newIndex].ctype = (particles[newIndex].tmp2<<16) | (particles[newIndex].tmp<<8) | particles[newIndex].ctype;
particles[newIndex].tmp = 1;
}
break;
case PT_FIRW:
if (particles[newIndex].tmp>=2 && savedVersion < 81)
{
int caddress = restrict_flt(restrict_flt((float)(particles[newIndex].tmp-4), 0.0f, 200.0f)*3, 0.0f, (200.0f*3)-3);
particles[newIndex].type = PT_EMBR;
particles[newIndex].tmp = 1;
particles[newIndex].ctype = (((unsigned char)(firw_data[caddress]))<<16) | (((unsigned char)(firw_data[caddress+1]))<<8) | ((unsigned char)(firw_data[caddress+2]));
}
break;
case PT_PSTN:
if (savedVersion < 87 && particles[newIndex].ctype)
particles[newIndex].life = 1;
break;
case PT_STKM:
case PT_STKM2:
case PT_FIGH:
if (savedVersion < 88 && particles[newIndex].ctype == OLD_SPC_AIR)
particles[newIndex].ctype = SPC_AIR;
break;
case PT_FILT:
if (savedVersion < 89)
{
if (particles[newIndex].tmp<0 || particles[newIndex].tmp>3)
particles[newIndex].tmp = 6;
particles[newIndex].ctype = 0;
}
break;
case PT_QRTZ:
case PT_PQRT:
if (savedVersion < 89)
{
particles[newIndex].tmp2 = particles[newIndex].tmp;
particles[newIndex].tmp = particles[newIndex].ctype;
particles[newIndex].ctype = 0;
}
break;
}
PT_SOAP will have its link data (ctype) set to the binary NOT of
0x06 which apparently clears the link data. Afterwards the link
data will be recreated.
PT_BOMB with non-0 tmp (when the version is before 81) will be re-
created as PT_EMBR because before 81 the sparkles were not EMBR
at all.
PT_DUST will too turn to PT_EMBR with non-0 TMP and save version
before 81 as it was used as firework glow.
PT_FIRW will also turn to PT_EMBR if it's in glow mode.
PT_PSTN will have its life set to 1 if its save version is below 87
and it has a ctype.
PT_STKM, PT_STKM2 and PT_FIGH, (with save version lt 88) if they have the ctype
OLD_SPC_AIR, will have their ctypes changed to SPC_AIR.
PT_FILT will have (with save version lt 89), its tmp turned to 6 if it's less
than 0 or more than 3, new tmp will be set to 6. The ctype will as well be
set to 0.
For QRTZ and PQRT, before version 89, the tmp2 will be set to the tmp,
the tmp set to the ctype and the ctype to 0.
That's about it for custom properties.
Soap links
----------
There are two indexes saved per soap particle: the "next" and "previous" linked
index. So basically in the end we'll have a doubly linked list of SOAP. The saved
soap links array has three bytes and keeps the "next" links only.
Three bytes at a time, like this:
[next, x-next, x-x-next]
linkedIndex = x-x-next << 16 | x-next << 8 | next;
newIndex = current particle being 'modified' by the parts data loop
To attach the two particles, do like the below code does:
//Attach the two particles
particles[newIndex].ctype |= 2;
particles[newIndex].tmp = linkedIndex;
particles[linkedIndex].ctype |= 4;
particles[linkedIndex].tmp2 = newIndex;
Written on the eve of 14th November 2013 by boxmein. It can be out of date but it might not be.
As an extra, open this page with "#[optionally usual anchor,]contrast" to make this page less
purple and more black-on-white.


Hi {{ applicant.name }},
It seems that your last connection on our application website was on the {{ applicant.updatedAt }}.
Are you still motivated for joining the {{ applicant.process.label }} in {{ applicant.process.location }}.
You have still a few days to complete your application, the deadline is the {{ applicant.process.deadline }}.
If you don't want to join us anymore, you can send us an email and we will stop sending you reminders.
See you soon in Social Hackers Academy!
Social Hackers Academy Team


The personal questionnaire for part-time Bachelor programmes
PERSONAL DATA
Surname (family name):
Name (names) /first name/:
Gender:
male
female
Father's first name:
Mother's first name:
Date of birth:
Place of birth:
Citizenship (country):
BELARUS
GERMANY
LITHUANIA
POLAND
RUSSIAN FEDERATION
SLOVAKIA
UKRAINE


18 May 2009 - As of 06:00 GMT, 18 May 2009, 40 countries have officially reported 8829 cases of influenza A(H1N1) infection, including 74 deaths.
The breakdown of the number of laboratory-confirmed cases by country is given in the following table and map. The numbers are based on the information provided to WHO by national health authorities.
| Countries officially reporting cases | Cumulative total of confirmed cases including deaths (as of 18 May 2009 06:00 GMT) | Newly confirmed cases including deaths since 17 May 2009 | ||
| Cases | Deaths | Cases | Deaths | |
| Argentina | 1 | 0 | 0 | 0 |
| Australia | 1 | 0 | 0 | 0 |
| Austria | 1 | 0 | 0 | 0 |
| Belgium | 5 | 0 | 1 | 0 |
| Brazil | 8 | 0 | 0 | 0 |
| Canada | 496 | 1 | 0 | 0 |
| Chile | 1 | 0 | 1 | 0 |
| China | 6 | 0 | 1 | 0 |
| Colombia | 11 | 0 | 0 | 0 |
| Costa Rica | 9 | 1 | 0 | 0 |
| Cuba | 3 | 0 | 0 | 0 |
| Denmark | 1 | 0 | 0 | 0 |
| Ecuador | 1 | 0 | 0 | 0 |
| El Salvador | 4 | 0 | 0 | 0 |
| Finland | 2 | 0 | 0 | 0 |
| France | 14 | 0 | 0 | 0 |
| Germany | 14 | 0 | 0 | 0 |
| Guatemala | 3 | 0 | 0 | 0 |
| India | 1 | 0 | 0 | 0 |
| Ireland | 1 | 0 | 0 | 0 |
| Israel | 7 | 0 | 0 | 0 |
| Italy | 9 | 0 | 0 | 0 |
| Japan | 125 | 0 | 118 | 0 |
| Korea, Republic of | 3 | 0 | 0 | 0 |
| Malaysia | 2 | 0 | 0 | 0 |
| Mexico | 3103 | 68 | 208 | 2 |
| Netherlands | 3 | 0 | 0 | 0 |
| New Zealand | 9 | 0 | 0 | 0 |
| Norway | 2 | 0 | 0 | 0 |
| Panama | 54 | 0 | 0 | 0 |
| Peru | 1 | 0 | 0 | 0 |
| Poland | 1 | 0 | 0 | 0 |
| Portugal | 1 | 0 | 0 | 0 |
| Spain | 103 | 0 | 0 | 0 |
| Sweden | 3 | 0 | 0 | 0 |
| Switzerland | 1 | 0 | 0 | 0 |
| Thailand | 2 | 0 | 0 | 0 |
| Turkey | 2 | 0 | 1 | 0 |
| UK | 101 | 0 | 19 | 0 |
| United States of America | 4714 | 4 | 0 | 0 |
| Total | 8829 | 74 | 349 | 2 |


| ORC-76 |
Update website with ORC 1.1.1 |
Major |
. |
Owen O'Malley |
Owen O'Malley |
| ORC-79 |
Minor updates to the website. |
Major |
. |
Owen O'Malley |
Owen O'Malley |
| ORC-80 |
C++ build breaks due to warnings with gcc-4.9 |
Major |
. |
Deepak Majeti |
Deepak Majeti |
| ORC-82 |
Fix compilation on ubuntu 12. |
Major |
. |
Owen O'Malley |
Owen O'Malley |
| ORC-83 |
Protected users from Reader.rows(Options) modifying the Options object |
Major |
. |
Owen O'Malley |
Owen O'Malley |
| ORC-88 |
Add a raw metadata switch to orc-metadata |
Major |
. |
Owen O'Malley |
Owen O'Malley |
| ORC-81 |
Add support for lzo and lz4 to c++ reader |
Major |
. |
Owen O'Malley |
Owen O'Malley |
| ORC-77 |
Support Snappy, LZO, and LZ4 from aircompressor. |
Major |
. |
Owen O'Malley |
Owen O'Malley |
| ORC-93 |
remove log message about seeking into an empty stream |
Major |
. |
Owen O'Malley |
Owen O'Malley |
| ORC-94 |
Remove obsolete MaxPermSize from pom file |
Major |
. |
Owen O'Malley |
Owen O'Malley |
| ORC-95 |
Fix some missing ASF headers |
Major |
. |
Owen O'Malley |
Owen O'Malley |


Use "Set Key" to attach access key to selected devices.
(The Access Key is used as querystring accessKey=theKey of URL when access device's live capture or recorded files)
To Enable Remote Access to Stream Web...
Set ip = "*" or some explicit IP address in stream.json file.
Optionally, set ssl.on = true to Enable SSL on Stream Web.
Restart this application.
To Enable SSL on Stream Web...
Set ssl.on = true in stream.json file.
Optionally, configure certificateFilePath or replace PKCS12 file ./ssl/StreamWeb.pfx with yours.
Restart this application.
To Enable Authentication on Admin Web...
Set adminKey in stream.json file to any string you like. Example: "adminKey": "xxxx"
Restart this application.
Open this menu page by the URL appended with adminKey=yourAdminKey querystring. Example: https://<IP_ADDRESS>/?adminKey=xxxx
To Enable Remote Access to Admin Web...
Set adminWeb.ip = "*" or some explicit IP address in stream.json file.
Optionally, set adminWeb.ssl.on = true to Enable SSL on Admin Web.
Restart this application.
To Enable SSL on Admin Web...
Set adminWeb.ssl.on = true in stream.json file.
Optionally, configure adminWeb.certificateFilePath or replace PKCS12 file ./ssl/AdminWeb.pfx with yours.
Restart this application.
To report an issue: https://github.com/sjitech/sji-android-screen-capture/issues/new


Preparation time
less than 30 mins
Cooking time
over 2 hours
Serves
Serves 8
A pork joint coated in crunchy crackling is always welcome at the table, but when it’s Delia Smith’s perfect roast pork, it’s the guest of honour.
Pre-heat the oven to 240C/475F/Gas 9.
While the oven is preheating, score the skin of the pork. It will be scored already, but it's always best to add a few more lines. To do this you can use the point of a very sharp paring knife, or Stanley knife, or you can now even buy a special scalpel from a good quality kitchen shop! What you need to do is score the skin all over into thin strips, bringing the blade of the knife about halfway through the fat beneath the skin.
Now place the pork in a tin, skin-side up, halve the onion and wedge the two pieces in slightly underneath the meat. Now take about 1 tbsp of crushed salt crystals and sprinkle it evenly over the skin, pressing it in as much as you can.
Place the pork on a high shelf in the oven and roast it for 25 minutes. Turn the heat down to 190C/375F/Gas 5, and calculate the total cooking time allowing 35 minutes to the pound, then deduct the initial 25 minutes cooking time. In this case it would be a further 2½ hours.
There's no need to baste pork as there is enough fat to keep the meat moist. The way to tell if the meat is cooked is to insert a skewer in the thickest part and the juices that run out should be absolutely clear without any trace of pinkness.
When the pork is cooked remove it from the oven and give it at least 30 minutes resting time before carving. While that is happening, tilt the tin and spoon all the fat off, leaving only the juces. The onion will probably be black and charred, which gives the gravy a lovely rich colour. Leave the onion in, then place the roasting tin over direct heat, turned to low, sprinkle in the flour and quickly work it into the juices with a wooden spoon.
Now turn the heat up to medium and gradually add the cider and the stock, this time using a balloon whisk until it comes up to simmering point and you have a smooth rich gravy. Taste and season with salt and pepper, then discard the onion and pour the gravy into a warmed serving jug. Serve the pork carved in slices, giving everyone some crackling.
You need JavaScript to view this clip.
How to carve roast pork
You need JavaScript to view this clip.
Scoring skin