Vector rework;

This commit is contained in:
bjorn 2019-07-01 02:16:13 -07:00 committed by Bjorn
parent 39f8203442
commit 9156fa2cbf
19 changed files with 5256 additions and 2990 deletions

View File

@ -16,7 +16,6 @@ LOVR_EXPORT int luaopen_lovr_timer(lua_State* L);
extern const luaL_Reg lovrModules[];
// Objects
extern const luaL_Reg lovrLightUserdata[];
extern const luaL_Reg lovrAudioStream[];
extern const luaL_Reg lovrBallJoint[];
extern const luaL_Reg lovrBlob[];
@ -36,7 +35,6 @@ extern const luaL_Reg lovrMesh[];
extern const luaL_Reg lovrMicrophone[];
extern const luaL_Reg lovrModel[];
extern const luaL_Reg lovrModelData[];
extern const luaL_Reg lovrPool[];
extern const luaL_Reg lovrQuat[];
extern const luaL_Reg lovrRandomGenerator[];
extern const luaL_Reg lovrRasterizer[];
@ -49,6 +47,7 @@ extern const luaL_Reg lovrSphereShape[];
extern const luaL_Reg lovrTexture[];
extern const luaL_Reg lovrTextureData[];
extern const luaL_Reg lovrThread[];
extern const luaL_Reg lovrVec2[];
extern const luaL_Reg lovrVec3[];
extern const luaL_Reg lovrWorld[];
@ -112,10 +111,9 @@ void luax_readattachments(lua_State* L, int index, struct Attachment* attachment
#include <stdint.h>
#include "math/pool.h" // TODO
#include "math/randomGenerator.h" // TODO
void luax_pushlightmathtype(lua_State* L, float* p, MathType type);
float* luax_tomathtype(lua_State* L, int index, MathType* type);
float* luax_checkmathtype(lua_State* L, int index, MathType type, const char* expected);
float* luax_newmathtype(lua_State* L, MathType type);
float* luax_tovector(lua_State* L, int index, VectorType* type);
float* luax_checkvector(lua_State* L, int index, VectorType type, const char* expected);
float* luax_newtempvector(lua_State* L, VectorType type);
int luax_readvec3(lua_State* L, int index, float* v, const char* expected);
int luax_readscale(lua_State* L, int index, float* v, int components, const char* expected);
int luax_readquat(lua_State* L, int index, float* q, const char* expected);

View File

@ -267,7 +267,7 @@ static void luax_readvertices(lua_State* L, int index, float* v, uint32_t count)
lua_pop(L, 1);
for (uint32_t i = 0; i < count; i++) {
lua_rawgeti(L, index, i + 1);
vec3_init(v, luax_checkmathtype(L, -1, MATH_VEC3, NULL));
vec3_init(v, luax_checkvector(L, -1, V_VEC3, NULL));
lua_pop(L, 1);
v[3] = v[4] = v[5] = v[6] = v[7] = 0.f;
v += 8;
@ -287,7 +287,7 @@ static void luax_readvertices(lua_State* L, int index, float* v, uint32_t count)
default:
for (uint32_t i = 0; i < count; i++) {
vec3_init(v, luax_checkmathtype(L, index + i, MATH_VEC3, NULL));
vec3_init(v, luax_checkvector(L, index + i, V_VEC3, NULL));
v[3] = v[4] = v[5] = v[6] = v[7] = 0.f;
v += 8;
}

View File

@ -1,226 +0,0 @@
#include "api.h"
#include "math/math.h"
#include "math/pool.h"
#include "core/maf.h"
int luax_readmat4(lua_State* L, int index, mat4 m, int scaleComponents) {
switch (lua_type(L, index)) {
case LUA_TNIL:
case LUA_TNONE:
mat4_identity(m);
return index + 1;
case LUA_TLIGHTUSERDATA:
case LUA_TUSERDATA:
default: {
MathType type;
float* p = luax_tomathtype(L, index, &type);
if (type == MATH_MAT4) {
mat4_init(m, p);
return index + 1;
}
} // Fall through
case LUA_TNUMBER: {
float S[4];
float R[4];
mat4_identity(m);
index = luax_readvec3(L, index, m + 12, "mat4, vec3, or number");
index = luax_readscale(L, index, S, scaleComponents, NULL);
index = luax_readquat(L, index, R, NULL);
mat4_rotateQuat(m, R);
mat4_scale(m, S[0], S[1], S[2]);
m[15] = 1.f;
return index;
}
}
}
static int l_lovrMat4Unpack(lua_State* L) {
mat4 m = luax_checkmathtype(L, 1, MATH_MAT4, NULL);
if (lua_toboolean(L, 2)) {
for (int i = 0; i < 16; i++) {
lua_pushnumber(L, m[i]);
}
return 16;
} else {
float angle, ax, ay, az;
float position[4], orientation[4], scale[4];
mat4_getPosition(m, position);
mat4_getScale(m, scale);
mat4_getOrientation(m, orientation);
quat_getAngleAxis(orientation, &angle, &ax, &ay, &az);
lua_pushnumber(L, position[0]);
lua_pushnumber(L, position[1]);
lua_pushnumber(L, position[2]);
lua_pushnumber(L, scale[0]);
lua_pushnumber(L, scale[1]);
lua_pushnumber(L, scale[2]);
lua_pushnumber(L, angle);
lua_pushnumber(L, ax);
lua_pushnumber(L, ay);
lua_pushnumber(L, az);
return 10;
}
}
int l_lovrMat4Set(lua_State* L) {
mat4 m = luax_checkmathtype(L, 1, MATH_MAT4, NULL);
if (lua_gettop(L) >= 17) {
for (int i = 2; i <= 17; i++) {
*m++ = luaL_checknumber(L, i);
}
} else {
luax_readmat4(L, 2, m, 3);
}
lua_settop(L, 1);
return 1;
}
static int l_lovrMat4Identity(lua_State* L) {
mat4 m = luax_checkmathtype(L, 1, MATH_MAT4, NULL);
mat4_identity(m);
lua_settop(L, 1);
return 1;
}
static int l_lovrMat4Invert(lua_State* L) {
mat4 m = luax_checkmathtype(L, 1, MATH_MAT4, NULL);
mat4_invert(m);
lua_settop(L, 1);
return 1;
}
static int l_lovrMat4Transpose(lua_State* L) {
mat4 m = luax_checkmathtype(L, 1, MATH_MAT4, NULL);
mat4_transpose(m);
lua_settop(L, 1);
return 1;
}
static int l_lovrMat4Translate(lua_State* L) {
mat4 m = luax_checkmathtype(L, 1, MATH_MAT4, NULL);
if (lua_type(L, 2) == LUA_TNUMBER) {
mat4_translate(m, luax_checkfloat(L, 2), luax_checkfloat(L, 3), luax_checkfloat(L, 4));
} else {
float* v = luax_checkmathtype(L, 2, MATH_VEC3, "vec3 or number");
mat4_translate(m, v[0], v[1], v[2]);
}
lua_settop(L, 1);
return 1;
}
static int l_lovrMat4Rotate(lua_State* L) {
mat4 m = luax_checkmathtype(L, 1, MATH_MAT4, NULL);
if (lua_type(L, 2) == LUA_TNUMBER) {
mat4_rotate(m, luax_checkfloat(L, 2), luax_checkfloat(L, 3), luax_checkfloat(L, 4), luax_checkfloat(L, 5));
} else {
float* q = luax_checkmathtype(L, 2, MATH_QUAT, "quat or number");
mat4_rotateQuat(m, q);
}
lua_settop(L, 1);
return 1;
}
static int l_lovrMat4Scale(lua_State* L) {
mat4 m = luax_checkmathtype(L, 1, MATH_MAT4, NULL);
if (lua_type(L, 2) == LUA_TNUMBER) {
float x = luax_checkfloat(L, 2);
mat4_scale(m, x, luax_optfloat(L, 3, x), luax_optfloat(L, 4, x));
} else {
float* s = luax_checkmathtype(L, 2, MATH_VEC3, "vec3 or number");
mat4_scale(m, s[0], s[1], s[2]);
}
lua_settop(L, 1);
return 1;
}
static int l_lovrMat4Mul(lua_State* L) {
mat4 m = luax_checkmathtype(L, 1, MATH_MAT4, NULL);
MathType type;
float* n = luax_tomathtype(L, 2, &type);
if (n && type == MATH_MAT4) {
mat4_multiply(m, n);
lua_settop(L, 1);
return 1;
} else if (n && type == MATH_VEC3) {
mat4_transform(m, n);
lua_settop(L, 2);
return 1;
} else if (lua_type(L, 2) == LUA_TNUMBER) {
float x = luaL_checknumber(L, 2);
float y = luaL_optnumber(L, 3, 0.f);
float z = luaL_optnumber(L, 4, 0.f);
float v[4] = { x, y, z };
mat4_transform(m, v);
lua_pushnumber(L, v[0]);
lua_pushnumber(L, v[1]);
lua_pushnumber(L, v[2]);
return 3;
} else {
return luaL_typerror(L, 2, "mat4, vec3, or number");
}
}
static int l_lovrMat4Perspective(lua_State* L) {
mat4 m = luax_checkmathtype(L, 1, MATH_MAT4, NULL);
float clipNear = luax_checkfloat(L, 2);
float clipFar = luax_checkfloat(L, 3);
float fov = luax_checkfloat(L, 4);
float aspect = luax_checkfloat(L, 5);
mat4_perspective(m, clipNear, clipFar, fov, aspect);
lua_settop(L, 1);
return 1;
}
static int l_lovrMat4Orthographic(lua_State* L) {
mat4 m = luax_checkmathtype(L, 1, MATH_MAT4, NULL);
float left = luax_checkfloat(L, 2);
float right = luax_checkfloat(L, 3);
float top = luax_checkfloat(L, 4);
float bottom = luax_checkfloat(L, 5);
float clipNear = luax_checkfloat(L, 6);
float clipFar = luax_checkfloat(L, 7);
mat4_orthographic(m, left, right, top, bottom, clipNear, clipFar);
lua_settop(L, 1);
return 1;
}
static int l_lovrMat4__mul(lua_State* L) {
mat4 m = luax_checkmathtype(L, 1, MATH_MAT4, NULL);
MathType type;
float* n = luax_tomathtype(L, 2, &type);
if (!n || type == MATH_QUAT) return luaL_typerror(L, 2, "mat4 or vec3");
if (type == MATH_MAT4) {
mat4 out = luax_newmathtype(L, MATH_MAT4);
mat4_multiply(mat4_init(out, m), n);
} else {
vec3 out = luax_newmathtype(L, MATH_VEC3);
vec3_init(out, n);
mat4_transform(m, n);
}
return 1;
}
static int l_lovrMat4__tostring(lua_State* L) {
luax_checkmathtype(L, 1, MATH_MAT4, NULL);
lua_pushliteral(L, "mat4");
return 1;
}
const luaL_Reg lovrMat4[] = {
{ "unpack", l_lovrMat4Unpack },
{ "set", l_lovrMat4Set },
{ "identity", l_lovrMat4Identity },
{ "invert", l_lovrMat4Invert },
{ "transpose", l_lovrMat4Transpose },
{ "translate", l_lovrMat4Translate },
{ "rotate", l_lovrMat4Rotate },
{ "scale", l_lovrMat4Scale },
{ "mul", l_lovrMat4Mul },
{ "perspective", l_lovrMat4Perspective },
{ "orthographic", l_lovrMat4Orthographic },
{ "__mul", l_lovrMat4__mul },
{ "__tostring", l_lovrMat4__tostring },
{ NULL, NULL }
};

View File

@ -6,78 +6,102 @@
#include "resources/math.lua.h"
#include "core/maf.h"
#include "core/ref.h"
#include "core/util.h"
#include <stdlib.h>
int l_lovrRandomGeneratorRandom(lua_State* L);
int l_lovrRandomGeneratorRandomNormal(lua_State* L);
int l_lovrRandomGeneratorGetSeed(lua_State* L);
int l_lovrRandomGeneratorSetSeed(lua_State* L);
int l_lovrVec2Set(lua_State* L);
int l_lovrVec3Set(lua_State* L);
int l_lovrQuatSet(lua_State* L);
int l_lovrMat4Set(lua_State* L);
static const char* lovrMathTypeNames[] = {
[MATH_VEC3] = "vec3",
[MATH_QUAT] = "quat",
[MATH_MAT4] = "mat4"
static LOVR_THREAD_LOCAL Pool* pool;
static const luaL_Reg* lovrVectorMetatables[] = {
[V_VEC2] = lovrVec2,
[V_VEC3] = lovrVec3,
[V_QUAT] = lovrQuat,
[V_MAT4] = lovrMat4
};
static const luaL_Reg* lovrMathTypes[] = {
[MATH_VEC3] = lovrVec3,
[MATH_QUAT] = lovrQuat,
[MATH_MAT4] = lovrMat4
static int lovrVectorMetatableRefs[] = {
[V_VEC2] = LUA_REFNIL,
[V_VEC3] = LUA_REFNIL,
[V_QUAT] = LUA_REFNIL,
[V_MAT4] = LUA_REFNIL
};
static const int lovrMathTypeComponents[] = {
[MATH_VEC3] = 3,
[MATH_QUAT] = 4,
[MATH_MAT4] = 16
static const char* lovrVectorTypeNames[] = {
[V_VEC2] = "vec2",
[V_VEC3] = "vec3",
[V_QUAT] = "quat",
[V_MAT4] = "mat4"
};
static float* luax_tolightmathtype(lua_State* L, int index, MathType* type) {
uintptr_t p = (uintptr_t) lua_touserdata(L, index), aligned = ALIGN(p, POOL_ALIGN);
*type = p - aligned;
return p ? (float*) aligned : NULL;
static void luax_destroypool(void) {
lovrRelease(Pool, pool);
}
void luax_pushlightmathtype(lua_State* L, float* p, MathType type) {
lua_pushlightuserdata(L, (uint8_t*) p + type);
}
float* luax_tomathtype(lua_State* L, int index, MathType* type) {
float* luax_tovector(lua_State* L, int index, VectorType* type) {
int luaType = lua_type(L, index);
if (luaType == LUA_TLIGHTUSERDATA) {
return luax_tolightmathtype(L, index, type);
} else if (luaType == LUA_TUSERDATA) {
MathType* x = lua_touserdata(L, index);
*type = *x;
return (float*) (x + 1);
union { void* pointer; Vector handle; } u;
u.pointer = lua_touserdata(L, index);
if (u.pointer && u.handle.type > V_NONE && u.handle.type < MAX_VECTOR_TYPES) {
*type = u.handle.type;
return lovrPoolResolve(pool, u.handle);
}
} else if (luaType > LUA_TTHREAD) { // cdata
lua_getfield(L, index, "_type");
*type = lua_tonumber(L, -1);
lua_pop(L, 1);
lua_getfield(L, index, "_p");
float* p = *(float**) lua_topointer(L, -1);
lua_pop(L, 1);
return p;
Vector* handle = (Vector*) lua_topointer(L, index);
if (handle && handle->type > V_NONE && handle->type < MAX_VECTOR_TYPES) {
*type = handle->type;
return lovrPoolResolve(pool, *handle);
}
} else if (luaType == LUA_TUSERDATA) {
VectorType* p = lua_touserdata(L, index);
if (p && *p > V_NONE && *p < MAX_VECTOR_TYPES) {
*type = *p;
return (float*) (p + 1);
}
}
*type = V_NONE;
return NULL;
}
float* luax_checkmathtype(lua_State* L, int index, MathType type, const char* expected) {
MathType t;
float* p = luax_tomathtype(L, index, &t);
if (!p || t != type) luaL_typerror(L, index, expected ? expected : lovrMathTypeNames[type]);
float* luax_checkvector(lua_State* L, int index, VectorType type, const char* expected) {
VectorType t;
float* p = luax_tovector(L, index, &t);
if (!p || t != type) luaL_typerror(L, index, expected ? expected : lovrVectorTypeNames[type]);
return p;
}
float* luax_newmathtype(lua_State* L, MathType type) {
MathType* x = (MathType*) lua_newuserdata(L, sizeof(MathType) + lovrMathTypeComponents[type] * sizeof(float));
luaL_getmetatable(L, lovrMathTypeNames[type]);
static float* luax_newvector(lua_State* L, VectorType type, size_t components) {
VectorType* p = lua_newuserdata(L, sizeof(VectorType) + components * sizeof(float));
*p = type;
lua_rawgeti(L, LUA_REGISTRYINDEX, lovrVectorMetatableRefs[type]);
lua_setmetatable(L, -2);
*x = type;
return (float*) (x + 1);
return (float*) (p + 1);
}
float* luax_newtempvector(lua_State* L, VectorType type) {
float* data;
Vector handle = lovrPoolAllocate(pool, type, &data);
union { void* pointer; Vector handle; } u;
u.handle = handle;
lua_pushlightuserdata(L, u.pointer);
return data;
}
static int l_lovrVectorGetPointer(lua_State* L) {
if (lua_type(L, 1) == LUA_TUSERDATA) {
VectorType* p = lua_touserdata(L, 1);
lua_pushlightuserdata(L, p + 1);
return 1;
}
return 0;
}
static int l_lovrMathNewCurve(lua_State* L) {
@ -111,14 +135,6 @@ static int l_lovrMathNewCurve(lua_State* L) {
return 1;
}
static int l_lovrMathNewPool(lua_State* L) {
size_t size = luaL_optinteger(L, 1, DEFAULT_POOL_SIZE);
Pool* pool = lovrPoolCreate(size);
luax_pushtype(L, Pool, pool);
lovrRelease(Pool, pool);
return 1;
}
static int l_lovrMathNewRandomGenerator(lua_State* L) {
RandomGenerator* generator = lovrRandomGeneratorCreate();
if (lua_gettop(L) > 0){
@ -130,34 +146,6 @@ static int l_lovrMathNewRandomGenerator(lua_State* L) {
return 1;
}
static int l_lovrMathLookAt(lua_State* L) {
float from[4] = { luax_checkfloat(L, 1), luax_checkfloat(L, 2), luax_checkfloat(L, 3) };
float to[4] = { luax_checkfloat(L, 4), luax_checkfloat(L, 5), luax_checkfloat(L, 6) };
float up[4] = { luax_optfloat(L, 7, 0.f), luax_optfloat(L, 8, 1.f), luax_optfloat(L, 9, 0.f) };
float m[16], q[4], angle, ax, ay, az;
mat4_lookAt(m, from, to, up);
quat_fromMat4(q, m);
quat_getAngleAxis(q, &angle, &ax, &ay, &az);
lua_pushnumber(L, -angle);
lua_pushnumber(L, ax);
lua_pushnumber(L, ay);
lua_pushnumber(L, az);
return 4;
}
static int l_lovrMathOrientationToDirection(lua_State* L) {
float angle = luax_checkfloat(L, 1);
float ax = luax_optfloat(L, 2, 0.f);
float ay = luax_optfloat(L, 3, 1.f);
float az = luax_optfloat(L, 4, 0.f);
float v[4];
lovrMathOrientationToDirection(angle, ax, ay, az, v);
lua_pushnumber(L, v[0]);
lua_pushnumber(L, v[1]);
lua_pushnumber(L, v[2]);
return 3;
}
static int l_lovrMathNoise(lua_State* L) {
switch (lua_gettop(L)) {
case 0:
@ -229,30 +217,62 @@ static int l_lovrMathLinearToGamma(lua_State* L) {
}
}
static int l_lovrVec3__call(lua_State* L) {
luax_newmathtype(L, MATH_VEC3);
lua_replace(L, 1);
static int l_lovrMathNewVec2(lua_State* L) {
luax_newvector(L, V_VEC2, 2);
lua_insert(L, 1);
return l_lovrVec2Set(L);
}
static int l_lovrMathNewVec3(lua_State* L) {
luax_newvector(L, V_VEC3, 4);
lua_insert(L, 1);
return l_lovrVec3Set(L);
}
static int l_lovrQuat__call(lua_State* L) {
luax_newmathtype(L, MATH_QUAT);
lua_replace(L, 1);
static int l_lovrMathNewQuat(lua_State* L) {
luax_newvector(L, V_QUAT, 4);
lua_insert(L, 1);
return l_lovrQuatSet(L);
}
static int l_lovrMat4__call(lua_State* L) {
luax_newmathtype(L, MATH_MAT4);
lua_replace(L, 1);
static int l_lovrMathNewMat4(lua_State* L) {
luax_newvector(L, V_MAT4, 16);
lua_insert(L, 1);
return l_lovrMat4Set(L);
}
static int l_lovrMathVec2(lua_State* L) {
luax_newtempvector(L, V_VEC2);
lua_insert(L, 1);
return l_lovrVec2Set(L);
}
static int l_lovrMathVec3(lua_State* L) {
luax_newtempvector(L, V_VEC3);
lua_insert(L, 1);
return l_lovrVec3Set(L);
}
static int l_lovrMathQuat(lua_State* L) {
luax_newtempvector(L, V_QUAT);
lua_insert(L, 1);
return l_lovrQuatSet(L);
}
static int l_lovrMathMat4(lua_State* L) {
luax_newtempvector(L, V_MAT4);
lua_insert(L, 1);
return l_lovrMat4Set(L);
}
static int l_lovrMathDrain(lua_State* L) {
lovrPoolDrain(pool);
return 0;
}
static const luaL_Reg lovrMath[] = {
{ "newCurve", l_lovrMathNewCurve },
{ "newPool", l_lovrMathNewPool },
{ "newRandomGenerator", l_lovrMathNewRandomGenerator },
{ "orientationToDirection", l_lovrMathOrientationToDirection },
{ "lookAt", l_lovrMathLookAt },
{ "noise", l_lovrMathNoise },
{ "random", l_lovrMathRandom },
{ "randomNormal", l_lovrMathRandomNormal },
@ -260,27 +280,63 @@ static const luaL_Reg lovrMath[] = {
{ "setRandomSeed", l_lovrMathSetRandomSeed },
{ "gammaToLinear", l_lovrMathGammaToLinear },
{ "linearToGamma", l_lovrMathLinearToGamma },
{ "newVec2", l_lovrMathNewVec2 },
{ "newVec3", l_lovrMathNewVec3 },
{ "newQuat", l_lovrMathNewQuat },
{ "newMat4", l_lovrMathNewMat4 },
{ "vec2", l_lovrMathVec2 },
{ "vec3", l_lovrMathVec3 },
{ "quat", l_lovrMathQuat },
{ "mat4", l_lovrMathMat4 },
{ "drain", l_lovrMathDrain },
{ NULL, NULL }
};
static int l_lovrLightUserdata__index(lua_State* L) {
MathType type;
luax_tolightmathtype(L, 1, &type);
luaL_getmetatable(L, lovrMathTypeNames[type]);
VectorType type;
if (!luax_tovector(L, 1, &type)) {
return 0;
}
lua_rawgeti(L, LUA_REGISTRYINDEX, lovrVectorMetatableRefs[type]);
lua_pushvalue(L, 2);
lua_rawget(L, -2);
if (lua_isnil(L, -1)) {
lua_pop(L, 1);
lua_pushliteral(L, "__index");
lua_rawget(L, -2);
if (!lua_isnil(L, -1)) {
lua_pushvalue(L, 1);
lua_pushvalue(L, 2);
lua_call(L, 2, 1);
return 1;
} else {
return 0;
}
}
return 1;
}
static int l_lovrLightUserdataOp(lua_State* L) {
MathType type;
luax_tolightmathtype(L, 1, &type);
luaL_getmetatable(L, lovrMathTypeNames[type]);
VectorType type;
if (!luax_tovector(L, 1, &type)) {
lua_pushliteral(L, "__tostring");
if (lua_rawequal(L, -1, lua_upvalueindex(1))) {
lua_pop(L, 1);
lua_pushfstring(L, "%s: %p", lua_typename(L, lua_type(L, 1)), lua_topointer(L, 1));
return 1;
}
lua_pop(L, 1);
return luaL_error(L, "Unsupported lightuserdata operator %q", lua_tostring(L, lua_upvalueindex(1)));
}
lua_rawgeti(L, LUA_REGISTRYINDEX, lovrVectorMetatableRefs[type]);
lua_pushvalue(L, lua_upvalueindex(1));
lua_gettable(L, -2);
lua_pushvalue(L, 1);
lua_pushvalue(L, 2);
lua_call(L, 2, 1);
lua_pushvalue(L, 3);
lua_call(L, 3, 1);
return 1;
}
@ -288,46 +344,29 @@ int luaopen_lovr_math(lua_State* L) {
lua_newtable(L);
luaL_register(L, NULL, lovrMath);
luax_registertype(L, Curve);
luax_registertype(L, Pool);
luax_registertype(L, RandomGenerator);
for (int i = 0; i < MAX_MATH_TYPES; i++) {
_luax_registertype(L, lovrMathTypeNames[i], lovrMathTypes[i], NULL);
luaL_getmetatable(L, lovrMathTypeNames[i]);
// Remove usual __gc handler
lua_pushnil(L);
lua_setfield(L, -2, "__gc");
// Allow metatable to be called as a function
for (size_t i = V_NONE + 1; i < MAX_VECTOR_TYPES; i++) {
lua_newtable(L);
switch (i) {
case MATH_VEC3: lua_pushcfunction(L, l_lovrVec3__call); break;
case MATH_QUAT: lua_pushcfunction(L, l_lovrQuat__call); break;
case MATH_MAT4: lua_pushcfunction(L, l_lovrMat4__call); break;
default: break;
}
lua_setfield(L, -2, "__call");
lua_setmetatable(L, -2);
// Assign into the lovr.math table
lua_setfield(L, -2, lovrMathTypeNames[i]);
lua_pushstring(L, lovrVectorTypeNames[i]);
lua_setfield(L, -2, "__name");
lua_pushcfunction(L, l_lovrVectorGetPointer);
lua_setfield(L, -2, "getPointer");
luaL_register(L, NULL, lovrVectorMetatables[i]);
lovrVectorMetatableRefs[i] = luaL_ref(L, LUA_REGISTRYINDEX);
}
// Global lightuserdata metatable
lua_pushlightuserdata(L, NULL);
lua_newtable(L);
lua_pushcfunction(L, l_lovrLightUserdata__index);
lua_setfield(L, -2, "__index");
const char* ops[] = { "__add", "__sub", "__mul", "__div", "__unm", "__len", "__tostring" };
const char* ops[] = { "__add", "__sub", "__mul", "__div", "__unm", "__len", "__tostring", "__newindex" };
for (size_t i = 0; i < sizeof(ops) / sizeof(ops[0]); i++) {
lua_pushstring(L, ops[i]);
lua_pushcclosure(L, l_lovrLightUserdataOp, 1);
lua_setfield(L, -2, ops[i]);
}
lua_setmetatable(L, -2);
lua_pop(L, 1);
@ -336,26 +375,39 @@ int luaopen_lovr_math(lua_State* L) {
luax_atexit(L, lovrMathDestroy);
}
pool = lovrPoolCreate();
luax_atexit(L, luax_destroypool);
// Inject LuaJIT superjuice
#ifdef LOVR_USE_LUAJIT
luax_pushconf(L);
lua_getfield(L, -1, "math");
if (lua_istable(L, -1)) {
#ifdef LOVR_USE_LUAJIT
lua_getfield(L, -1, "ffi");
if (lua_toboolean(L, -1)) {
lua_pushcfunction(L, luax_getstack);
lovrAssert(!luaL_loadbuffer(L, (const char*) math_lua, math_lua_len, "math.lua"), "Could not load math.lua");
if (luaL_loadbuffer(L, (const char*) math_lua, math_lua_len, "math.lua")) {
lovrThrow(lua_tostring(L, -1));
}
lua_pushvalue(L, -6); // lovr.math
luaL_getmetatable(L, "Pool");
lua_pushlightuserdata(L, pool);
if (lua_pcall(L, 2, 0, -4)) {
lovrThrow(lua_tostring(L, -1));
}
lua_pop(L, 1);
}
lua_pop(L, 1);
#endif
lua_getfield(L, -1, "globals");
if (lua_toboolean(L, -1)) {
for (size_t i = V_NONE + 1; i < MAX_VECTOR_TYPES; i++) {
lua_getfield(L, -4, lovrVectorTypeNames[i]);
lua_setglobal(L, lovrVectorTypeNames[i]);
}
}
lua_pop(L, 1);
}
lua_pop(L, 2);
#endif
return 1;
}

View File

@ -1,74 +0,0 @@
#include "api.h"
#include "math/pool.h"
#include "core/maf.h"
int l_lovrVec3Set(lua_State* L);
int l_lovrQuatSet(lua_State* L);
int l_lovrMat4Set(lua_State* L);
static int l_lovrPoolVec3(lua_State* L) {
Pool* pool = luax_checktype(L, 1, Pool);
vec3 v = lovrPoolAllocate(pool, MATH_VEC3);
if (v) {
luax_pushlightmathtype(L, v, MATH_VEC3);
lua_replace(L, 1);
return l_lovrVec3Set(L);
} else {
lua_pushnil(L);
}
return 1;
}
static int l_lovrPoolQuat(lua_State* L) {
Pool* pool = luax_checktype(L, 1, Pool);
quat q = lovrPoolAllocate(pool, MATH_QUAT);
if (q) {
luax_pushlightmathtype(L, q, MATH_QUAT);
lua_replace(L, 1);
return l_lovrQuatSet(L);
} else {
lua_pushnil(L);
}
return 1;
}
static int l_lovrPoolMat4(lua_State* L) {
Pool* pool = luax_checktype(L, 1, Pool);
mat4 m = lovrPoolAllocate(pool, MATH_MAT4);
if (m) {
luax_pushlightmathtype(L, m, MATH_MAT4);
lua_replace(L, 1);
return l_lovrMat4Set(L);
} else {
lua_pushnil(L);
}
return 1;
}
static int l_lovrPoolDrain(lua_State* L) {
Pool* pool = luax_checktype(L, 1, Pool);
lovrPoolDrain(pool);
return 0;
}
static int l_lovrPoolGetSize(lua_State* L) {
Pool* pool = luax_checktype(L, 1, Pool);
lua_pushinteger(L, lovrPoolGetSize(pool));
return 1;
}
static int l_lovrPoolGetUsage(lua_State* L) {
Pool* pool = luax_checktype(L, 1, Pool);
lua_pushinteger(L, lovrPoolGetUsage(pool));
return 1;
}
const luaL_Reg lovrPool[] = {
{ "vec3", l_lovrPoolVec3 },
{ "quat", l_lovrPoolQuat },
{ "mat4", l_lovrPoolMat4 },
{ "drain", l_lovrPoolDrain },
{ "getSize", l_lovrPoolGetSize },
{ "getUsage", l_lovrPoolGetUsage },
{ NULL, NULL }
};

View File

@ -1,163 +0,0 @@
#include "api.h"
#include "math/math.h"
#include "core/maf.h"
int luax_readquat(lua_State* L, int index, quat q, const char* expected) {
float angle, ax, ay, az;
switch (lua_type(L, index)) {
case LUA_TNIL:
case LUA_TNONE:
quat_set(q, 0, 0, 0, 0);
return ++index;
case LUA_TNUMBER:
angle = luax_optfloat(L, index++, 0.f);
ax = luax_optfloat(L, index++, 0.f);
ay = luax_optfloat(L, index++, 1.f);
az = luax_optfloat(L, index++, 0.f);
quat_fromAngleAxis(q, angle, ax, ay, az);
return index;
default:
quat_init(q, luax_checkmathtype(L, index++, MATH_QUAT, expected ? expected : "quat or number"));
return index;
}
}
static int l_lovrQuatUnpack(lua_State* L) {
quat q = luax_checkmathtype(L, 1, MATH_QUAT, NULL);
bool raw = lua_toboolean(L, 2);
if (raw) {
lua_pushnumber(L, q[0]);
lua_pushnumber(L, q[1]);
lua_pushnumber(L, q[2]);
lua_pushnumber(L, q[3]);
} else {
float angle, ax, ay, az;
quat_getAngleAxis(q, &angle, &ax, &ay, &az);
lua_pushnumber(L, angle);
lua_pushnumber(L, ax);
lua_pushnumber(L, ay);
lua_pushnumber(L, az);
}
return 4;
}
int l_lovrQuatSet(lua_State* L) {
quat q = luax_checkmathtype(L, 1, MATH_QUAT, NULL);
if (lua_isnoneornil(L, 2)) {
quat_set(q, 0.f, 0.f, 0.f, 1.f);
} else if (lua_type(L, 2) == LUA_TNUMBER) {
float x = lua_tonumber(L, 2);
if (lua_type(L, 3) == LUA_TNUMBER) {
float y = luax_checkfloat(L, 3);
float z = luax_checkfloat(L, 4);
float w = luax_checkfloat(L, 5);
bool raw = lua_toboolean(L, 6);
if (raw) {
quat_set(q, x, y, z, w);
} else {
quat_fromAngleAxis(q, x, y, z, w);
}
} else {
vec3 axis = luax_checkmathtype(L, 3, MATH_VEC3, "vec3 or number");
quat_fromAngleAxis(q, x, axis[0], axis[1], axis[2]);
}
} else {
MathType type;
float* p = luax_tomathtype(L, 2, &type);
if (!p) return luaL_typerror(L, 2, "vec3, quat, or number");
if (type == MATH_VEC3) {
if (lua_gettop(L) > 2) {
vec3 u = luax_checkmathtype(L, 3, MATH_VEC3, "vec3");
quat_between(q, p, u);
} else {
quat_between(q, (float[4]) { 0.f, 0.f, -1.f }, p);
}
} else if (type == MATH_QUAT) {
quat_init(q, p);
} else if (type == MATH_MAT4) {
quat_fromMat4(q, p);
} else {
return luaL_typerror(L, 2, "vec3, quat, mat4, or number");
}
}
lua_settop(L, 1);
return 1;
}
static int l_lovrQuatMul(lua_State* L) {
quat q = luax_checkmathtype(L, 1, MATH_QUAT, NULL);
MathType type;
float* r = luax_tomathtype(L, 2, &type);
if (!r || type == MATH_MAT4) return luaL_typerror(L, 2, "quat or vec3");
if (type == MATH_VEC3) {
quat_rotate(q, r);
lua_settop(L, 2);
} else {
quat_mul(q, r);
lua_settop(L, 1);
}
return 1;
}
static int l_lovrQuatLength(lua_State* L) {
quat q = luax_checkmathtype(L, 1, MATH_QUAT, NULL);
lua_pushnumber(L, quat_length(q));
return 1;
}
static int l_lovrQuatNormalize(lua_State* L) {
quat q = luax_checkmathtype(L, 1, MATH_QUAT, NULL);
quat_normalize(q);
lua_settop(L, 1);
return 1;
}
static int l_lovrQuatSlerp(lua_State* L) {
quat q = luax_checkmathtype(L, 1, MATH_QUAT, NULL);
quat r = luax_checkmathtype(L, 2, MATH_QUAT, NULL);
float t = luax_checkfloat(L, 3);
quat_slerp(q, r, t);
lua_settop(L, 1);
return 1;
}
static int l_lovrQuat__mul(lua_State* L) {
quat q = luax_checkmathtype(L, 1, MATH_QUAT, NULL);
MathType type;
float* r = luax_tomathtype(L, 2, &type);
if (!r) return luaL_typerror(L, 2, "quat or vec3");
if (type == MATH_VEC3) {
vec3 out = luax_newmathtype(L, MATH_VEC3);
quat_rotate(q, vec3_init(out, r));
} else {
quat out = luax_newmathtype(L, MATH_QUAT);
quat_mul(quat_init(out, q), r);
}
return 1;
}
static int l_lovrQuat__len(lua_State* L) {
quat q = luax_checkmathtype(L, 1, MATH_QUAT, NULL);
lua_pushnumber(L, quat_length(q));
return 1;
}
static int l_lovrQuat__tostring(lua_State* L) {
quat q = luax_checkmathtype(L, 1, MATH_QUAT, NULL);
lua_pushfstring(L, "(%f, %f, %f, %f)", q[0], q[1], q[2], q[3]);
return 1;
}
const luaL_Reg lovrQuat[] = {
{ "unpack", l_lovrQuatUnpack },
{ "set", l_lovrQuatSet },
{ "mul", l_lovrQuatMul },
{ "length", l_lovrQuatLength },
{ "normalize", l_lovrQuatNormalize },
{ "slerp", l_lovrQuatSlerp },
{ "__mul", l_lovrQuat__mul },
{ "__len", l_lovrQuat__len },
{ "__tostring", l_lovrQuat__tostring },
{ NULL, NULL }
};

View File

@ -102,17 +102,17 @@ int luax_checkuniform(lua_State* L, int index, const Uniform* uniform, void* des
lua_rawgeti(L, index, i + 1);
if (uniformType == UNIFORM_MATRIX && components == 16) {
MathType type;
mat4 m = luax_tomathtype(L, -1, &type);
if (m && type == MATH_MAT4) {
VectorType type;
mat4 m = luax_tovector(L, -1, &type);
if (m && type == V_MAT4) {
mat4_init((float*) dest + i * components, m);
lua_pop(L, 1);
continue;
}
} else if (uniformType == UNIFORM_FLOAT && components == 3) {
MathType type;
vec3 v = luax_tomathtype(L, -1, &type);
if (v && type == MATH_VEC3) {
VectorType type;
vec3 v = luax_tovector(L, -1, &type);
if (v && type == V_VEC3) {
vec3_init((float*) dest + i * components, v);
lua_pop(L, 1);
continue;
@ -143,16 +143,16 @@ int luax_checkuniform(lua_State* L, int index, const Uniform* uniform, void* des
} else {
for (int i = 0; i < count; i++) {
if (uniformType == UNIFORM_MATRIX && components == 16) {
MathType type;
mat4 m = luax_tomathtype(L, index + i, &type);
if (m && type == MATH_MAT4) {
VectorType type;
mat4 m = luax_tovector(L, index + i, &type);
if (m && type == V_MAT4) {
mat4_init((float*) dest + i * components, m);
continue;
}
} else if (uniformType == UNIFORM_FLOAT && components == 3) {
MathType type;
vec3 v = luax_tomathtype(L, index + i, &type);
if (v && type == MATH_VEC3) {
VectorType type;
vec3 v = luax_tovector(L, index + i, &type);
if (v && type == V_VEC3) {
vec3_init((float*) dest + i * components, v);
continue;
}

View File

@ -1,265 +0,0 @@
#include "api.h"
#include "math/math.h"
#include "core/maf.h"
int luax_readvec3(lua_State* L, int index, vec3 v, const char* expected) {
switch (lua_type(L, index)) {
case LUA_TNIL:
case LUA_TNONE:
v[0] = v[1] = v[2] = 0.f;
return ++index;
case LUA_TNUMBER:
v[0] = luax_optfloat(L, index++, 0.f);
v[1] = luax_optfloat(L, index++, 0.f);
v[2] = luax_optfloat(L, index++, 0.f);
return index;
default:
vec3_init(v, luax_checkmathtype(L, index++, MATH_VEC3, expected ? expected : "vec3 or number"));
return index;
}
}
int luax_readscale(lua_State* L, int index, vec3 v, int components, const char* expected) {
switch (lua_type(L, index)) {
case LUA_TNIL:
case LUA_TNONE:
v[0] = v[1] = v[2] = 1.f;
return index + components;
case LUA_TNUMBER:
if (components == 1) {
v[0] = v[1] = v[2] = luax_optfloat(L, index++, 0.f);
} else {
v[0] = 1.f;
for (int i = 0; i < components; i++) {
v[i] = luax_optfloat(L, index++, v[0]);
}
}
return index;
default:
vec3_init(v, luax_checkmathtype(L, index++, MATH_VEC3, expected ? expected : "vec3 or number"));
return index;
}
}
static int l_lovrVec3Unpack(lua_State* L) {
vec3 v = luax_checkmathtype(L, 1, MATH_VEC3, NULL);
lua_pushnumber(L, v[0]);
lua_pushnumber(L, v[1]);
lua_pushnumber(L, v[2]);
return 3;
}
int l_lovrVec3Set(lua_State* L) {
vec3 v = luax_checkmathtype(L, 1, MATH_VEC3, NULL);
if (lua_isnoneornil(L, 2) || lua_type(L, 2) == LUA_TNUMBER) {
float x = luax_optfloat(L, 2, 0.f);
vec3_set(v, x, luax_optfloat(L, 3, x), luax_optfloat(L, 4, x));
} else {
vec3 u = luax_checkmathtype(L, 2, MATH_VEC3, "vec3 or number");
vec3_init(v, u);
}
lua_settop(L, 1);
return 1;
}
static int l_lovrVec3Add(lua_State* L) {
vec3 v = luax_checkmathtype(L, 1, MATH_VEC3, NULL);
if (lua_type(L, 2) == LUA_TNUMBER) {
float x = lua_tonumber(L, 2);
vec3_add(v, (float[4]) { x, luaL_optnumber(L, 3, x), luaL_optnumber(L, 4, x) });
} else {
vec3 u = luax_checkmathtype(L, 2, MATH_VEC3, "vec3 or number");
vec3_add(v, u);
}
lua_settop(L, 1);
return 1;
}
static int l_lovrVec3Sub(lua_State* L) {
vec3 v = luax_checkmathtype(L, 1, MATH_VEC3, NULL);
if (lua_type(L, 2) == LUA_TNUMBER) {
float x = lua_tonumber(L, 2);
vec3_sub(v, (float[4]) { x, luaL_optnumber(L, 3, x), luaL_optnumber(L, 4, x) });
} else {
vec3 u = luax_checkmathtype(L, 2, MATH_VEC3, "vec3 or number");
vec3_sub(v, u);
}
lua_settop(L, 1);
return 1;
}
static int l_lovrVec3Mul(lua_State* L) {
vec3 v = luax_checkmathtype(L, 1, MATH_VEC3, NULL);
if (lua_type(L, 2) == LUA_TNUMBER) {
vec3_scale(v, lua_tonumber(L, 2));
} else {
vec3 u = luax_checkmathtype(L, 2, MATH_VEC3, "vec3 or number");
v[0] = v[0] * u[0], v[1] = v[1] * u[1], v[2] = v[2] * u[2];
}
lua_settop(L, 1);
return 1;
}
static int l_lovrVec3Div(lua_State* L) {
vec3 v = luax_checkmathtype(L, 1, MATH_VEC3, NULL);
if (lua_type(L, 2) == LUA_TNUMBER) {
vec3_scale(v, 1.f / (float) lua_tonumber(L, 2));
} else {
vec3 u = luax_checkmathtype(L, 2, MATH_VEC3, "vec3 or number");
v[0] = v[0] / u[0], v[1] = v[1] / u[1], v[2] = v[2] / u[2];
}
lua_settop(L, 1);
return 1;
}
static int l_lovrVec3Length(lua_State* L) {
vec3 v = luax_checkmathtype(L, 1, MATH_VEC3, NULL);
lua_pushnumber(L, vec3_length(v));
return 1;
}
static int l_lovrVec3Normalize(lua_State* L) {
vec3 v = luax_checkmathtype(L, 1, MATH_VEC3, NULL);
vec3_normalize(v);
lua_settop(L, 1);
return 1;
}
static int l_lovrVec3Distance(lua_State* L) {
vec3 v = luax_checkmathtype(L, 1, MATH_VEC3, NULL);
vec3 u = luax_checkmathtype(L, 2, MATH_VEC3, NULL);
lua_pushnumber(L, vec3_distance(v, u));
return 1;
}
static int l_lovrVec3Dot(lua_State* L) {
vec3 v = luax_checkmathtype(L, 1, MATH_VEC3, NULL);
vec3 u = luax_checkmathtype(L, 2, MATH_VEC3, NULL);
lua_pushnumber(L, vec3_dot(v, u));
return 1;
}
static int l_lovrVec3Cross(lua_State* L) {
vec3 v = luax_checkmathtype(L, 1, MATH_VEC3, NULL);
vec3 u = luax_checkmathtype(L, 2, MATH_VEC3, NULL);
vec3_cross(v, u);
lua_settop(L, 1);
return 1;
}
static int l_lovrVec3Lerp(lua_State* L) {
vec3 v = luax_checkmathtype(L, 1, MATH_VEC3, NULL);
vec3 u = luax_checkmathtype(L, 2, MATH_VEC3, NULL);
float t = luax_checkfloat(L, 3);
vec3_lerp(v, u, t);
lua_settop(L, 1);
return 1;
}
static int l_lovrVec3Min(lua_State* L) {
vec3 v = luax_checkmathtype(L, 1, MATH_VEC3, NULL);
vec3 u = luax_checkmathtype(L, 2, MATH_VEC3, NULL);
vec3_min(v, u);
lua_settop(L, 1);
return 1;
}
static int l_lovrVec3Max(lua_State* L) {
vec3 v = luax_checkmathtype(L, 1, MATH_VEC3, NULL);
vec3 u = luax_checkmathtype(L, 2, MATH_VEC3, NULL);
vec3_max(v, u);
lua_settop(L, 1);
return 1;
}
static int l_lovrVec3__add(lua_State* L) {
vec3 v = luax_checkmathtype(L, 1, MATH_VEC3, NULL);
vec3 u = luax_checkmathtype(L, 2, MATH_VEC3, NULL);
vec3 out = luax_newmathtype(L, MATH_VEC3);
vec3_add(vec3_init(out, v), u);
return 1;
}
static int l_lovrVec3__sub(lua_State* L) {
vec3 v = luax_checkmathtype(L, 1, MATH_VEC3, NULL);
vec3 u = luax_checkmathtype(L, 2, MATH_VEC3, NULL);
vec3 out = luax_newmathtype(L, MATH_VEC3);
vec3_sub(vec3_init(out, v), u);
return 1;
}
static int l_lovrVec3__mul(lua_State* L) {
vec3 out = luax_newmathtype(L, MATH_VEC3);
if (lua_type(L, 1) == LUA_TNUMBER) {
vec3 u = luax_checkmathtype(L, 2, MATH_VEC3, NULL);
vec3_scale(vec3_init(out, u), lua_tonumber(L, 1));
} else if (lua_type(L, 2) == LUA_TNUMBER) {
vec3 v = luax_checkmathtype(L, 1, MATH_VEC3, NULL);
vec3_scale(vec3_init(out, v), lua_tonumber(L, 2));
} else {
vec3 v = luax_checkmathtype(L, 1, MATH_VEC3, NULL);
vec3 u = luax_checkmathtype(L, 2, MATH_VEC3, "vec3 or number");
out[0] = v[0] * u[0], out[1] = v[1] * u[1], out[2] = v[2] * u[2];
}
return 1;
}
static int l_lovrVec3__div(lua_State* L) {
vec3 out = luax_newmathtype(L, MATH_VEC3);
if (lua_type(L, 1) == LUA_TNUMBER) {
vec3 u = luax_checkmathtype(L, 2, MATH_VEC3, NULL);
vec3_scale(vec3_init(out, u), 1. / lua_tonumber(L, 1));
} else if (lua_type(L, 2) == LUA_TNUMBER) {
vec3 v = luax_checkmathtype(L, 1, MATH_VEC3, NULL);
vec3_scale(vec3_init(out, v), 1. / lua_tonumber(L, 2));
} else {
vec3 v = luax_checkmathtype(L, 1, MATH_VEC3, NULL);
vec3 u = luax_checkmathtype(L, 2, MATH_VEC3, "vec3 or number");
out[0] = v[0] / u[0], out[1] = v[1] / u[1], out[2] = v[2] / u[2];
}
return 1;
}
static int l_lovrVec3__unm(lua_State* L) {
vec3 v = luax_checkmathtype(L, 1, MATH_VEC3, NULL);
vec3 out = luax_newmathtype(L, MATH_VEC3);
vec3_scale(vec3_init(out, v), -1.f);
return 1;
}
static int l_lovrVec3__len(lua_State* L) {
vec3 v = luax_checkmathtype(L, 1, MATH_VEC3, NULL);
lua_pushnumber(L, vec3_length(v));
return 1;
}
static int l_lovrVec3__tostring(lua_State* L) {
vec3 v = luax_checkmathtype(L, 1, MATH_VEC3, NULL);
lua_pushfstring(L, "(%f, %f, %f)", v[0], v[1], v[2]);
return 1;
}
const luaL_Reg lovrVec3[] = {
{ "unpack", l_lovrVec3Unpack },
{ "set", l_lovrVec3Set },
{ "add", l_lovrVec3Add },
{ "sub", l_lovrVec3Sub },
{ "mul", l_lovrVec3Mul },
{ "div", l_lovrVec3Div },
{ "length", l_lovrVec3Length },
{ "normalize", l_lovrVec3Normalize },
{ "distance", l_lovrVec3Distance },
{ "dot", l_lovrVec3Dot },
{ "cross", l_lovrVec3Cross },
{ "lerp", l_lovrVec3Lerp },
{ "min", l_lovrVec3Min },
{ "max", l_lovrVec3Max },
{ "__add", l_lovrVec3__add },
{ "__sub", l_lovrVec3__sub },
{ "__mul", l_lovrVec3__mul },
{ "__div", l_lovrVec3__div },
{ "__unm", l_lovrVec3__unm },
{ "__len", l_lovrVec3__len },
{ "__tostring", l_lovrVec3__tostring },
{ NULL, NULL }
};

1267
src/api/l_vectors.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -184,6 +184,19 @@ MAF quat quat_normalize(quat q) {
return q;
}
MAF void quat_getDirection(quat q, float* x, float* y, float* z) {
*x = -(2.f * q[0] * q[2] + 2.f * q[3] * q[1]);
*y = -(2.f * q[1] * q[2] + 2.f * q[3] * q[0]);
*z = -(1.f - 2.f * q[0] * q[0] - 2.f * q[1] * q[1]);
}
MAF quat quat_conjugate(quat q) {
q[0] = -q[0];
q[1] = -q[1];
q[2] = -q[2];
return q;
}
MAF quat quat_slerp(quat q, quat r, float t) {
float dot = q[0] * r[0] + q[1] * r[1] + q[2] * r[2] + q[3] * r[3];
if (fabsf(dot) >= 1.f) {
@ -602,78 +615,40 @@ MAF mat4 mat4_fov(mat4 m, float left, float right, float up, float down, float c
}
MAF mat4 mat4_lookAt(mat4 m, vec3 from, vec3 to, vec3 up) {
float x0, x1, x2, y0, y1, y2, z0, z1, z2, len;
if (from[0] == to[0] && from[1] == to[1] && from[2] == to[2]) {
return mat4_identity(m);
}
z0 = from[0] - to[0];
z1 = from[1] - to[1];
z2 = from[2] - to[2];
len = 1.f / sqrtf(z0 * z0 + z1 * z1 + z2 * z2);
z0 *= len;
z1 *= len;
z2 *= len;
x0 = up[1] * z2 - up[2] * z1;
x1 = up[2] * z0 - up[0] * z2;
x2 = up[0] * z1 - up[1] * z0;
len = sqrtf(x0 * x0 + x1 * x1 + x2 * x2);
if (!len) {
x0 = 0;
x1 = 0;
x2 = 0;
} else {
len = 1 / len;
x0 *= len;
x1 *= len;
x2 *= len;
}
y0 = z1 * x2 - z2 * x1;
y1 = z2 * x0 - z0 * x2;
y2 = z0 * x1 - z1 * x0;
len = sqrtf(y0 * y0 + y1 * y1 + y2 * y2);
if (!len) {
y0 = 0;
y1 = 0;
y2 = 0;
} else {
len = 1 / len;
y0 *= len;
y1 *= len;
y2 *= len;
}
m[0] = x0;
m[1] = y0;
m[2] = z0;
m[3] = 0;
m[4] = x1;
m[5] = y1;
m[6] = z1;
m[7] = 0;
m[8] = x2;
m[9] = y2;
m[10] = z2;
m[11] = 0;
m[12] = -(x0 * from[0] + x1 * from[1] + x2 * from[2]);
m[13] = -(y0 * from[0] + y1 * from[1] + y2 * from[2]);
m[14] = -(z0 * from[0] + z1 * from[1] + z2 * from[2]);
m[15] = 1;
float z[4];
float x[4];
float y[4];
vec3_sub(vec3_init(z, to), from);
vec3_normalize(vec3_cross(vec3_init(x, up), z));
vec3_cross(vec3_init(y, z), x);
m[0] = x[0];
m[1] = y[0];
m[2] = z[0];
m[3] = 0.f;
m[4] = x[1];
m[5] = y[1];
m[6] = z[1];
m[7] = 0.f;
m[8] = x[2];
m[9] = y[2];
m[10] = z[2];
m[11] = 0.f;
m[12] = 0.f;
m[13] = 0.f;
m[14] = 0.f;
m[15] = 1.f;
return m;
}
MAF void mat4_transform(mat4 m, vec3 v) {
vec3_set(v,
v[0] * m[0] + v[1] * m[4] + v[2] * m[8] + m[12],
v[0] * m[1] + v[1] * m[5] + v[2] * m[9] + m[13],
v[0] * m[2] + v[1] * m[6] + v[2] * m[10] + m[14]
);
float x = v[0] * m[0] + v[1] * m[4] + v[2] * m[8] + m[12];
float y = v[0] * m[1] + v[1] * m[5] + v[2] * m[9] + m[13];
float z = v[0] * m[2] + v[1] * m[6] + v[2] * m[10] + m[14];
float w = v[0] * m[3] + v[1] * m[7] + v[2] * m[11] + m[15];
v[0] = x / w;
v[1] = y / w;
v[2] = z / w;
v[3] = w / w;
}
MAF void mat4_transform_project(mat4 m, vec3 v) {
@ -688,9 +663,12 @@ MAF void mat4_transform_project(mat4 m, vec3 v) {
}
MAF void mat4_transformDirection(mat4 m, vec3 v) {
vec3_set(v,
v[0] * m[0] + v[1] * m[4] + v[2] * m[8],
v[0] * m[1] + v[1] * m[5] + v[2] * m[9],
v[0] * m[2] + v[1] * m[6] + v[2] * m[10]
);
float x = v[0] * m[0] + v[1] * m[4] + v[2] * m[8];
float y = v[0] * m[1] + v[1] * m[5] + v[2] * m[9];
float z = v[0] * m[2] + v[1] * m[6] + v[2] * m[10];
float w = v[0] * m[3] + v[1] * m[7] + v[2] * m[11];
v[0] = x;
v[1] = y;
v[2] = z;
v[3] = w;
}

View File

@ -197,6 +197,7 @@ static void desktop_update(float dt) {
state.localVelocity[0] = left ? -movespeed : (right ? movespeed : state.localVelocity[0]);
state.localVelocity[1] = up ? movespeed : (down ? -movespeed : state.localVelocity[1]);
state.localVelocity[2] = front ? -movespeed : (back ? movespeed : state.localVelocity[2]);
state.localVelocity[3] = 0.f;
vec3_init(state.velocity, state.localVelocity);
mat4_transformDirection(state.transform, state.velocity);
vec3_scale(state.localVelocity, damping);

View File

@ -32,14 +32,6 @@ RandomGenerator* lovrMathGetRandomGenerator() {
return state.generator;
}
void lovrMathOrientationToDirection(float angle, float ax, float ay, float az, vec3 v) {
float sinTheta = sinf(angle);
float cosTheta = cosf(angle);
v[0] = sinTheta * -ay + (1.f - cosTheta) * -az * ax;
v[1] = sinTheta * ax + (1.f - cosTheta) * -az * ay;
v[2] = -cosTheta + (1.f - cosTheta) * -az * az;
}
float lovrMathGammaToLinear(float x) {
if (x <= .04045f) {
return x / 12.92f;

View File

@ -3,7 +3,6 @@
#pragma once
struct RandomGenerator;
bool lovrMathInit(void);
void lovrMathDestroy(void);
struct RandomGenerator* lovrMathGetRandomGenerator(void);

View File

@ -1,17 +1,17 @@
#include "math/pool.h"
#include <stdlib.h>
static const size_t sizeOfMathType[] = {
[MATH_VEC3] = 4 * sizeof(float),
[MATH_QUAT] = 4 * sizeof(float),
[MATH_MAT4] = 16 * sizeof(float)
#define POOL_ALIGN 16
static const size_t vectorComponents[] = {
[V_VEC2] = 2,
[V_VEC3] = 4,
[V_QUAT] = 4,
[V_MAT4] = 16
};
Pool* lovrPoolInit(Pool* pool, size_t size) {
pool->size = size;
pool->data = malloc(pool->size + POOL_ALIGN - 1);
pool->head = (uint8_t*) ALIGN((uint8_t*) pool->data + POOL_ALIGN - 1, POOL_ALIGN);
lovrAssert(pool->data, "Out of memory");
Pool* lovrPoolInit(Pool* pool) {
lovrPoolGrow(pool, 1 << 12);
return pool;
}
@ -20,26 +20,33 @@ void lovrPoolDestroy(void* ref) {
free(pool->data);
}
float* lovrPoolAllocate(Pool* pool, MathType type) {
size_t size = sizeOfMathType[type];
lovrAssert(pool->usage + size <= pool->size, "Pool overflow");
float* p = (float*) (pool->head + pool->usage);
pool->usage += size;
return p;
void lovrPoolGrow(Pool* pool, size_t count) {
lovrAssert(count <= (1 << 16), "Congratulations! You have run out of memory for vectors. Try using lovr.math.drain to drain the vector Pool periodically."); // Only 24 bits for vector handles
pool->count = count;
pool->data = realloc(pool->data, pool->count * sizeof(float));
lovrAssert(pool->data, "Out of memory");
pool->floats = (float*) ALIGN((uint8_t*) pool->data + POOL_ALIGN - 1, POOL_ALIGN);
}
Vector lovrPoolAllocate(Pool* pool, VectorType type, float** data) {
size_t count = vectorComponents[type];
if (pool->cursor + count > pool->count - 4) { // Leave 4 floats of padding for alignment adjustment
lovrPoolGrow(pool, pool->count * 2);
}
Vector v = { type, pool->generation, pool->cursor };
if (data) {
*data = pool->floats + pool->cursor;
}
pool->cursor += count;
return v;
}
float* lovrPoolResolve(Pool* pool, Vector vector) {
lovrAssert(vector.generation == pool->generation, "Attempt to use a vector in a different generation than the one it was created in (vectors can not be saved into variables)");
return pool->floats + vector.index;
}
void lovrPoolDrain(Pool* pool) {
pool->usage = 0;
pool->cursor = 0;
pool->generation = (pool->generation + 1) & 0xff;
}
size_t lovrPoolGetSize(Pool* pool) {
return pool->size;
}
size_t lovrPoolGetUsage(Pool* pool) {
return pool->usage;
}
float* lovrPoolAllocateVec3(Pool* pool) { return lovrPoolAllocate(pool, MATH_VEC3); }
float* lovrPoolAllocateQuat(Pool* pool) { return lovrPoolAllocate(pool, MATH_QUAT); }
float* lovrPoolAllocateMat4(Pool* pool) { return lovrPoolAllocate(pool, MATH_MAT4); }

View File

@ -2,34 +2,35 @@
#include <stdint.h>
#include <stddef.h>
#define POOL_ALIGN 16
#define DEFAULT_POOL_SIZE (640 * 1024)
#pragma once
typedef enum {
MATH_VEC3,
MATH_QUAT,
MATH_MAT4,
MAX_MATH_TYPES
} MathType;
V_NONE,
V_VEC2,
V_VEC3,
V_QUAT,
V_MAT4,
MAX_VECTOR_TYPES
} VectorType;
typedef struct {
float* data;
size_t size;
size_t usage;
uint8_t* head;
uint8_t type;
uint8_t generation;
uint16_t index;
} Vector;
typedef struct Pool {
void* data;
float* floats;
size_t count;
size_t cursor;
size_t generation;
} Pool;
Pool* lovrPoolInit(Pool* pool, size_t size);
#define lovrPoolCreate(...) lovrPoolInit(lovrAlloc(Pool), __VA_ARGS__)
Pool* lovrPoolInit(Pool* pool);
#define lovrPoolCreate(...) lovrPoolInit(lovrAlloc(Pool))
void lovrPoolDestroy(void* ref);
float* lovrPoolAllocate(Pool* pool, MathType type);
LOVR_EXPORT void lovrPoolGrow(Pool* pool, size_t count);
Vector lovrPoolAllocate(Pool* pool, VectorType type, float** data);
float* lovrPoolResolve(Pool* pool, Vector vector);
void lovrPoolDrain(Pool* pool);
size_t lovrPoolGetSize(Pool* pool);
size_t lovrPoolGetUsage(Pool* pool);
// For you, LuaJIT
LOVR_EXPORT float* lovrPoolAllocateVec3(Pool* pool);
LOVR_EXPORT float* lovrPoolAllocateQuat(Pool* pool);
LOVR_EXPORT float* lovrPoolAllocateMat4(Pool* pool);

View File

@ -98,7 +98,8 @@ function lovr.boot()
msaa = 4
},
math = {
ffi = true
ffi = true,
globals = true
},
window = {
width = 1080,
@ -174,6 +175,9 @@ function lovr.run()
end
lovr.graphics.present()
end
if lovr.math then
lovr.math.drain()
end
end
end

View File

@ -244,482 +244,489 @@ unsigned char boot_lua[] = {
0x73, 0x61, 0x61, 0x20, 0x3d, 0x20, 0x34, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x7d, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x61, 0x74, 0x68, 0x20,
0x3d, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x66,
0x69, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x7d, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x6e, 0x64,
0x6f, 0x77, 0x20, 0x3d, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x31, 0x30, 0x38,
0x30, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x68, 0x65, 0x69,
0x67, 0x68, 0x74, 0x20, 0x3d, 0x20, 0x36, 0x30, 0x30, 0x2c, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x73, 0x63, 0x72,
0x65, 0x65, 0x6e, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x73, 0x61, 0x61, 0x20,
0x3d, 0x20, 0x30, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74,
0x69, 0x74, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x27, 0x4c, 0xc3, 0x96, 0x56,
0x52, 0x27, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x63,
0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x2c, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x76, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x3d, 0x20,
0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x7d, 0x0a,
0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x66, 0x69, 0x6c, 0x65,
0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x71,
0x75, 0x69, 0x72, 0x65, 0x28, 0x27, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x66,
0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x27, 0x29, 0x0a,
0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x68, 0x61, 0x73, 0x43,
0x6f, 0x6e, 0x66, 0x2c, 0x20, 0x68, 0x61, 0x73, 0x4d, 0x61, 0x69, 0x6e,
0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x66, 0x69, 0x6c, 0x65,
0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x69, 0x73, 0x46, 0x69, 0x6c,
0x65, 0x28, 0x27, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x6c, 0x75, 0x61, 0x27,
0x29, 0x2c, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x66, 0x69, 0x6c, 0x65,
0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x2e, 0x69, 0x73, 0x46, 0x69, 0x6c,
0x65, 0x28, 0x27, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x6c, 0x75, 0x61, 0x27,
0x29, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74,
0x65, 0x6d, 0x2e, 0x67, 0x65, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x28, 0x29, 0x20, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x28, 0x68,
0x61, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x20, 0x6f, 0x72, 0x20, 0x68, 0x61,
0x73, 0x4d, 0x61, 0x69, 0x6e, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20,
0x6e, 0x6f, 0x67, 0x61, 0x6d, 0x65, 0x28, 0x29, 0x20, 0x65, 0x6e, 0x64,
0x0a, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x63, 0x6f,
0x6e, 0x66, 0x4f, 0x6b, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x45, 0x72,
0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a, 0x20,
0x20, 0x69, 0x66, 0x20, 0x68, 0x61, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x20,
0x74, 0x68, 0x65, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x4f, 0x6b, 0x2c,
0x20, 0x63, 0x6f, 0x6e, 0x66, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d,
0x20, 0x70, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x72, 0x65, 0x71, 0x75, 0x69,
0x72, 0x65, 0x2c, 0x20, 0x27, 0x63, 0x6f, 0x6e, 0x66, 0x27, 0x29, 0x20,
0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x63, 0x6f, 0x6e,
0x66, 0x4f, 0x6b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x72,
0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x63,
0x6f, 0x6e, 0x66, 0x4f, 0x6b, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x45,
0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x70, 0x63, 0x61, 0x6c, 0x6c,
0x28, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x2c, 0x20,
0x63, 0x6f, 0x6e, 0x66, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x20,
0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x5f, 0x73, 0x65, 0x74, 0x43, 0x6f,
0x6e, 0x66, 0x28, 0x63, 0x6f, 0x6e, 0x66, 0x29, 0x0a, 0x20, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74,
0x65, 0x6d, 0x2e, 0x73, 0x65, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69,
0x74, 0x79, 0x28, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x69, 0x64, 0x65, 0x6e,
0x74, 0x69, 0x74, 0x79, 0x29, 0x0a, 0x0a, 0x20, 0x20, 0x66, 0x6f, 0x72,
0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x70,
0x61, 0x69, 0x72, 0x73, 0x28, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x6d, 0x6f,
0x64, 0x75, 0x6c, 0x65, 0x73, 0x29, 0x20, 0x64, 0x6f, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x69, 0x66, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x6d, 0x6f,
0x64, 0x75, 0x6c, 0x65, 0x73, 0x5b, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65,
0x5d, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6f, 0x6b, 0x2c, 0x20, 0x72,
0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x70, 0x63, 0x61, 0x6c,
0x6c, 0x28, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x2c, 0x20, 0x27,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x27, 0x20, 0x2e, 0x2e, 0x20, 0x6d, 0x6f,
0x64, 0x75, 0x6c, 0x65, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x6b, 0x20, 0x74, 0x68,
0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70,
0x72, 0x69, 0x6e, 0x74, 0x28, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e,
0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x28, 0x27, 0x57, 0x61, 0x72, 0x6e,
0x69, 0x6e, 0x67, 0x3a, 0x20, 0x43, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6e,
0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x6d, 0x6f, 0x64, 0x75,
0x6c, 0x65, 0x20, 0x25, 0x71, 0x3a, 0x20, 0x25, 0x73, 0x27, 0x2c, 0x20,
0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x2c, 0x20, 0x72, 0x65, 0x73, 0x75,
0x6c, 0x74, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65,
0x6c, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x6c, 0x6f, 0x76, 0x72, 0x5b, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5d,
0x20, 0x3d, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x20,
0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65,
0x72, 0x73, 0x20, 0x3d, 0x20, 0x73, 0x65, 0x74, 0x6d, 0x65, 0x74, 0x61,
0x74, 0x61, 0x62, 0x6c, 0x65, 0x28, 0x7b, 0x7d, 0x2c, 0x20, 0x7b, 0x20,
0x5f, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x20, 0x7d, 0x29, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6e,
0x6f, 0x74, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x4f, 0x6b, 0x20, 0x74, 0x68,
0x65, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x63, 0x6f, 0x6e,
0x66, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a,
0x20, 0x20, 0x69, 0x66, 0x20, 0x68, 0x61, 0x73, 0x4d, 0x61, 0x69, 0x6e,
0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72,
0x65, 0x20, 0x27, 0x6d, 0x61, 0x69, 0x6e, 0x27, 0x20, 0x65, 0x6e, 0x64,
0x0a, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x72, 0x75, 0x6e, 0x28, 0x29, 0x0a, 0x65, 0x6e, 0x64,
0x0a, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x72, 0x75, 0x6e, 0x28, 0x29, 0x0a, 0x20, 0x20,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x2e, 0x73,
0x74, 0x65, 0x70, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x74, 0x68, 0x65,
0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x6c, 0x6f, 0x61, 0x64, 0x28,
0x61, 0x72, 0x67, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x72,
0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x75, 0x6d, 0x70,
0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6e,
0x61, 0x6d, 0x65, 0x2c, 0x20, 0x61, 0x2c, 0x20, 0x62, 0x2c, 0x20, 0x63,
0x2c, 0x20, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x6f, 0x6c, 0x6c, 0x28, 0x29,
0x20, 0x64, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66,
0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x27, 0x71, 0x75,
0x69, 0x74, 0x27, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x28, 0x6e, 0x6f, 0x74,
0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x71, 0x75, 0x69, 0x74, 0x20, 0x6f,
0x72, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x71,
0x75, 0x69, 0x74, 0x28, 0x29, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75,
0x72, 0x6e, 0x20, 0x61, 0x20, 0x6f, 0x72, 0x20, 0x30, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x61,
0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x5b, 0x6e, 0x61, 0x6d, 0x65, 0x5d,
0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68,
0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73, 0x5b, 0x6e, 0x61, 0x6d, 0x65,
0x5d, 0x28, 0x61, 0x2c, 0x20, 0x62, 0x2c, 0x20, 0x63, 0x2c, 0x20, 0x64,
0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e,
0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20,
0x64, 0x74, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x74, 0x69,
0x6d, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x65, 0x70, 0x28, 0x29, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68,
0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68,
0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x75, 0x70, 0x64, 0x61, 0x74,
0x65, 0x28, 0x64, 0x74, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e,
0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x6e,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x61, 0x75, 0x64, 0x69, 0x6f, 0x2e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65,
0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74,
0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f,
0x2e, 0x73, 0x65, 0x74, 0x50, 0x6f, 0x73, 0x65, 0x28, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x67, 0x65,
0x74, 0x50, 0x6f, 0x73, 0x65, 0x28, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x61, 0x75,
0x64, 0x69, 0x6f, 0x2e, 0x73, 0x65, 0x74, 0x56, 0x65, 0x6c, 0x6f, 0x63,
0x69, 0x74, 0x79, 0x28, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61,
0x64, 0x73, 0x65, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x56, 0x65, 0x6c, 0x6f,
0x63, 0x69, 0x74, 0x79, 0x28, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x69, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x2c, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x73, 0x20,
0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x7d,
0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77,
0x20, 0x3d, 0x20, 0x7b, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x77,
0x69, 0x64, 0x74, 0x68, 0x20, 0x3d, 0x20, 0x31, 0x30, 0x38, 0x30, 0x2c,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x68, 0x65, 0x69, 0x67, 0x68,
0x74, 0x20, 0x3d, 0x20, 0x36, 0x30, 0x30, 0x2c, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x66, 0x75, 0x6c, 0x6c, 0x73, 0x63, 0x72, 0x65, 0x65,
0x6e, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x2c, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x6d, 0x73, 0x61, 0x61, 0x20, 0x3d, 0x20,
0x30, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x69, 0x74,
0x6c, 0x65, 0x20, 0x3d, 0x20, 0x27, 0x4c, 0xc3, 0x96, 0x56, 0x52, 0x27,
0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x63, 0x6f, 0x6e,
0x20, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x76, 0x73, 0x79, 0x6e, 0x63, 0x20, 0x3d, 0x20, 0x31, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x7d, 0x0a, 0x20, 0x20, 0x7d, 0x0a, 0x0a, 0x20,
0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79,
0x73, 0x74, 0x65, 0x6d, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69,
0x72, 0x65, 0x28, 0x27, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x66, 0x69, 0x6c,
0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x27, 0x29, 0x0a, 0x20, 0x20,
0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x68, 0x61, 0x73, 0x43, 0x6f, 0x6e,
0x66, 0x2c, 0x20, 0x68, 0x61, 0x73, 0x4d, 0x61, 0x69, 0x6e, 0x20, 0x3d,
0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79,
0x73, 0x74, 0x65, 0x6d, 0x2e, 0x69, 0x73, 0x46, 0x69, 0x6c, 0x65, 0x28,
0x27, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x6c, 0x75, 0x61, 0x27, 0x29, 0x2c,
0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79,
0x73, 0x74, 0x65, 0x6d, 0x2e, 0x69, 0x73, 0x46, 0x69, 0x6c, 0x65, 0x28,
0x27, 0x6d, 0x61, 0x69, 0x6e, 0x2e, 0x6c, 0x75, 0x61, 0x27, 0x29, 0x0a,
0x20, 0x20, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
0x2e, 0x67, 0x65, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x28, 0x29,
0x20, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x28, 0x68, 0x61, 0x73,
0x43, 0x6f, 0x6e, 0x66, 0x20, 0x6f, 0x72, 0x20, 0x68, 0x61, 0x73, 0x4d,
0x61, 0x69, 0x6e, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x6e, 0x6f,
0x67, 0x61, 0x6d, 0x65, 0x28, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x0a,
0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x63, 0x6f, 0x6e, 0x66,
0x4f, 0x6b, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x45, 0x72, 0x72, 0x6f,
0x72, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65, 0x0a, 0x20, 0x20, 0x69,
0x66, 0x20, 0x68, 0x61, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x20, 0x74, 0x68,
0x65, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x4f, 0x6b, 0x2c, 0x20, 0x63,
0x6f, 0x6e, 0x66, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20, 0x70,
0x63, 0x61, 0x6c, 0x6c, 0x28, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65,
0x2c, 0x20, 0x27, 0x63, 0x6f, 0x6e, 0x66, 0x27, 0x29, 0x20, 0x65, 0x6e,
0x64, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x4f,
0x6b, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x63,
0x6f, 0x6e, 0x66, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x63, 0x6f, 0x6e,
0x66, 0x4f, 0x6b, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x45, 0x72, 0x72,
0x6f, 0x72, 0x20, 0x3d, 0x20, 0x70, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x63, 0x6f, 0x6e, 0x66, 0x2c, 0x20, 0x63, 0x6f,
0x6e, 0x66, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x20, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x5f, 0x73, 0x65, 0x74, 0x43, 0x6f, 0x6e, 0x66,
0x28, 0x63, 0x6f, 0x6e, 0x66, 0x29, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d,
0x2e, 0x73, 0x65, 0x74, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79,
0x28, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69,
0x74, 0x79, 0x29, 0x0a, 0x0a, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6d,
0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x69, 0x6e, 0x20, 0x70, 0x61, 0x69,
0x72, 0x73, 0x28, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x6d, 0x6f, 0x64, 0x75,
0x6c, 0x65, 0x73, 0x29, 0x20, 0x64, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x69, 0x66, 0x20, 0x63, 0x6f, 0x6e, 0x66, 0x2e, 0x6d, 0x6f, 0x64, 0x75,
0x6c, 0x65, 0x73, 0x5b, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5d, 0x20,
0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c,
0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6f, 0x6b, 0x2c, 0x20, 0x72, 0x65, 0x73,
0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x70, 0x63, 0x61, 0x6c, 0x6c, 0x28,
0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x2c, 0x20, 0x27, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x27, 0x20, 0x2e, 0x2e, 0x20, 0x6d, 0x6f, 0x64, 0x75,
0x6c, 0x65, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66,
0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x6b, 0x20, 0x74, 0x68, 0x65, 0x6e,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x72, 0x69,
0x6e, 0x74, 0x28, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x66, 0x6f,
0x72, 0x6d, 0x61, 0x74, 0x28, 0x27, 0x57, 0x61, 0x72, 0x6e, 0x69, 0x6e,
0x67, 0x3a, 0x20, 0x43, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x6e, 0x6f, 0x74,
0x20, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65,
0x20, 0x25, 0x71, 0x3a, 0x20, 0x25, 0x73, 0x27, 0x2c, 0x20, 0x6d, 0x6f,
0x64, 0x75, 0x6c, 0x65, 0x2c, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74,
0x29, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73,
0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x5b, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x5d, 0x20, 0x3d,
0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e,
0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x74, 0x68, 0x65,
0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x75, 0x70, 0x64, 0x61, 0x74,
0x65, 0x28, 0x64, 0x74, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72,
0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67,
0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x6f, 0x72, 0x69, 0x67,
0x69, 0x6e, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69,
0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x64, 0x72, 0x61, 0x77, 0x20,
0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x64, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x20, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x73,
0x20, 0x3d, 0x20, 0x73, 0x65, 0x74, 0x6d, 0x65, 0x74, 0x61, 0x74, 0x61,
0x62, 0x6c, 0x65, 0x28, 0x7b, 0x7d, 0x2c, 0x20, 0x7b, 0x20, 0x5f, 0x5f,
0x69, 0x6e, 0x64, 0x65, 0x78, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x72,
0x20, 0x7d, 0x29, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74,
0x20, 0x63, 0x6f, 0x6e, 0x66, 0x4f, 0x6b, 0x20, 0x74, 0x68, 0x65, 0x6e,
0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x63, 0x6f, 0x6e, 0x66, 0x45,
0x72, 0x72, 0x6f, 0x72, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20,
0x69, 0x66, 0x20, 0x68, 0x61, 0x73, 0x4d, 0x61, 0x69, 0x6e, 0x20, 0x74,
0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x20,
0x27, 0x6d, 0x61, 0x69, 0x6e, 0x27, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20,
0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72,
0x2e, 0x72, 0x75, 0x6e, 0x28, 0x29, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a,
0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x72, 0x75, 0x6e, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x65,
0x70, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x6c, 0x6f, 0x61, 0x64, 0x28, 0x61, 0x72,
0x67, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x72, 0x65, 0x74,
0x75, 0x72, 0x6e, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x75, 0x6d, 0x70, 0x28, 0x29,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x61, 0x6d,
0x65, 0x2c, 0x20, 0x61, 0x2c, 0x20, 0x62, 0x2c, 0x20, 0x63, 0x2c, 0x20,
0x64, 0x20, 0x69, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x65, 0x76,
0x65, 0x6e, 0x74, 0x2e, 0x70, 0x6f, 0x6c, 0x6c, 0x28, 0x29, 0x20, 0x64,
0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6e,
0x61, 0x6d, 0x65, 0x20, 0x3d, 0x3d, 0x20, 0x27, 0x71, 0x75, 0x69, 0x74,
0x27, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x28, 0x6e, 0x6f, 0x74, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x71, 0x75, 0x69, 0x74, 0x20, 0x6f, 0x72, 0x20,
0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x71, 0x75, 0x69,
0x74, 0x28, 0x29, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e,
0x20, 0x61, 0x20, 0x6f, 0x72, 0x20, 0x30, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x61, 0x6e, 0x64,
0x6c, 0x65, 0x72, 0x73, 0x5b, 0x6e, 0x61, 0x6d, 0x65, 0x5d, 0x20, 0x74,
0x68, 0x65, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x61, 0x6e,
0x64, 0x6c, 0x65, 0x72, 0x73, 0x5b, 0x6e, 0x61, 0x6d, 0x65, 0x5d, 0x28,
0x61, 0x2c, 0x20, 0x62, 0x2c, 0x20, 0x63, 0x2c, 0x20, 0x64, 0x29, 0x20,
0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x74,
0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x74, 0x69, 0x6d, 0x65,
0x72, 0x2e, 0x73, 0x74, 0x65, 0x70, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61,
0x64, 0x73, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72,
0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x72, 0x65, 0x6e,
0x64, 0x65, 0x72, 0x54, 0x6f, 0x28, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x64,
0x72, 0x61, 0x77, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61,
0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x68, 0x61, 0x73, 0x57, 0x69, 0x6e,
0x64, 0x6f, 0x77, 0x28, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x6d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x29, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70,
0x68, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74,
0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20,
0x20, 0x65, 0x6e, 0x64, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x66, 0x75,
0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x6d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x69,
0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61,
0x64, 0x73, 0x65, 0x74, 0x2e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x28,
0x64, 0x74, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x61, 0x75, 0x64, 0x69, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x61, 0x75,
0x64, 0x69, 0x6f, 0x2e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x28, 0x29,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x20, 0x74,
0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x2e, 0x73,
0x65, 0x74, 0x50, 0x6f, 0x73, 0x65, 0x28, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x50,
0x6f, 0x73, 0x65, 0x28, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x61, 0x75, 0x64, 0x69,
0x6f, 0x2e, 0x73, 0x65, 0x74, 0x56, 0x65, 0x6c, 0x6f, 0x63, 0x69, 0x74,
0x79, 0x28, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73,
0x65, 0x74, 0x2e, 0x67, 0x65, 0x74, 0x56, 0x65, 0x6c, 0x6f, 0x63, 0x69,
0x74, 0x79, 0x28, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x28,
0x64, 0x74, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70,
0x68, 0x69, 0x63, 0x73, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61,
0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e,
0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x64, 0x72, 0x61, 0x77, 0x20, 0x74, 0x68,
0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69,
0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73,
0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x2d, 0x2d, 0x20, 0x4f,
0x6e, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x73, 0x79, 0x73, 0x74, 0x65,
0x6d, 0x73, 0x2c, 0x20, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x20,
0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
0x62, 0x65, 0x20, 0x64, 0x69, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x74, 0x65,
0x78, 0x74, 0x75, 0x72, 0x65, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x72,
0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x67, 0x65, 0x74,
0x4d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x54, 0x65, 0x78, 0x74, 0x75, 0x72,
0x65, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x74,
0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20,
0x20, 0x20, 0x20, 0x2d, 0x2d, 0x20, 0x4f, 0x6e, 0x20, 0x73, 0x6f, 0x6d,
0x65, 0x20, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x73, 0x2c, 0x20, 0x74,
0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x20, 0x69, 0x73, 0x20, 0x70, 0x72,
0x69, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74,
0x6c, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77, 0x69,
0x6e, 0x64, 0x6f, 0x77, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73,
0x2e, 0x66, 0x69, 0x6c, 0x6c, 0x28, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72,
0x65, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20,
0x20, 0x65, 0x6c, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e,
0x63, 0x6c, 0x65, 0x61, 0x72, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x64, 0x72, 0x61, 0x77, 0x28, 0x29, 0x0a,
0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x6c,
0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x54, 0x72, 0x61, 0x63,
0x65, 0x62, 0x61, 0x63, 0x6b, 0x28, 0x73, 0x29, 0x0a, 0x20, 0x20, 0x72,
0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x73, 0x3a, 0x67, 0x73, 0x75, 0x62,
0x28, 0x27, 0x5c, 0x6e, 0x5b, 0x5e, 0x5c, 0x6e, 0x5d, 0x2b, 0x24, 0x27,
0x2c, 0x20, 0x27, 0x27, 0x29, 0x3a, 0x67, 0x73, 0x75, 0x62, 0x28, 0x27,
0x5c, 0x74, 0x27, 0x2c, 0x20, 0x27, 0x27, 0x29, 0x3a, 0x67, 0x73, 0x75,
0x62, 0x28, 0x27, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x20, 0x74, 0x72, 0x61,
0x63, 0x65, 0x62, 0x61, 0x63, 0x6b, 0x27, 0x2c, 0x20, 0x27, 0x5c, 0x6e,
0x53, 0x74, 0x61, 0x63, 0x6b, 0x27, 0x29, 0x0a, 0x65, 0x6e, 0x64, 0x0a,
0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x65, 0x72, 0x72, 0x68, 0x61, 0x6e, 0x64, 0x28, 0x6d,
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x74, 0x72, 0x61, 0x63,
0x65, 0x62, 0x61, 0x63, 0x6b, 0x29, 0x0a, 0x20, 0x20, 0x6d, 0x65, 0x73,
0x73, 0x61, 0x67, 0x65, 0x20, 0x3d, 0x20, 0x74, 0x6f, 0x73, 0x74, 0x72,
0x69, 0x6e, 0x67, 0x28, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x29,
0x0a, 0x20, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x3d,
0x20, 0x27, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x3a, 0x5c, 0x6e, 0x27, 0x20,
0x2e, 0x2e, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x2e,
0x2e, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x54, 0x72, 0x61, 0x63,
0x65, 0x62, 0x61, 0x63, 0x6b, 0x28, 0x74, 0x72, 0x61, 0x63, 0x65, 0x62,
0x61, 0x63, 0x6b, 0x20, 0x6f, 0x72, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67,
0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x62, 0x61, 0x63, 0x6b, 0x28, 0x27,
0x27, 0x2c, 0x20, 0x34, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x70, 0x72, 0x69,
0x6e, 0x74, 0x28, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x29, 0x0a,
0x20, 0x20, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x20, 0x74,
0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66,
0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x20, 0x72, 0x65,
0x74, 0x75, 0x72, 0x6e, 0x20, 0x31, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x65,
0x6e, 0x64, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72,
0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x72, 0x65, 0x73, 0x65, 0x74,
0x28, 0x29, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72,
0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x73, 0x65, 0x74, 0x42, 0x61,
0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64, 0x43, 0x6f, 0x6c, 0x6f,
0x72, 0x28, 0x2e, 0x31, 0x30, 0x35, 0x2c, 0x20, 0x2e, 0x30, 0x39, 0x38,
0x2c, 0x20, 0x2e, 0x31, 0x33, 0x37, 0x29, 0x0a, 0x20, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e,
0x73, 0x65, 0x74, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x2e, 0x38, 0x36,
0x33, 0x2c, 0x20, 0x2e, 0x38, 0x36, 0x33, 0x2c, 0x20, 0x2e, 0x38, 0x36,
0x33, 0x29, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66,
0x6f, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67,
0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x67, 0x65, 0x74, 0x46,
0x6f, 0x6e, 0x74, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x66, 0x6f, 0x6e, 0x74,
0x3a, 0x73, 0x65, 0x74, 0x46, 0x6c, 0x69, 0x70, 0x45, 0x6e, 0x61, 0x62,
0x6c, 0x65, 0x64, 0x28, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x29, 0x0a, 0x20,
0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c,
0x44, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x20, 0x3d, 0x20, 0x66, 0x6f,
0x6e, 0x74, 0x3a, 0x67, 0x65, 0x74, 0x50, 0x69, 0x78, 0x65, 0x6c, 0x44,
0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x6c,
0x6f, 0x63, 0x61, 0x6c, 0x20, 0x77, 0x69, 0x64, 0x74, 0x68, 0x20, 0x3d,
0x20, 0x66, 0x6f, 0x6e, 0x74, 0x3a, 0x67, 0x65, 0x74, 0x57, 0x69, 0x64,
0x74, 0x68, 0x28, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2c, 0x20,
0x2e, 0x35, 0x35, 0x20, 0x2a, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x44,
0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x29, 0x0a, 0x20, 0x20, 0x6c, 0x6f,
0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x20, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x28, 0x29, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68,
0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x6d, 0x65,
0x73, 0x73, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x2d, 0x77, 0x69, 0x64, 0x74,
0x68, 0x20, 0x2f, 0x20, 0x32, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x2d, 0x32,
0x30, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20,
0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x2e, 0x35, 0x35, 0x20, 0x2a, 0x20,
0x70, 0x69, 0x78, 0x65, 0x6c, 0x44, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79,
0x2c, 0x20, 0x27, 0x6c, 0x65, 0x66, 0x74, 0x27, 0x29, 0x0a, 0x20, 0x20,
0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e,
0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x65, 0x76, 0x65,
0x6e, 0x74, 0x2e, 0x70, 0x75, 0x6d, 0x70, 0x28, 0x29, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20,
0x61, 0x20, 0x69, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x65, 0x76,
0x65, 0x6e, 0x74, 0x2e, 0x70, 0x6f, 0x6c, 0x6c, 0x28, 0x29, 0x20, 0x64,
0x6f, 0x20, 0x69, 0x66, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x3d, 0x3d,
0x20, 0x27, 0x71, 0x75, 0x69, 0x74, 0x27, 0x20, 0x74, 0x68, 0x65, 0x6e,
0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x20, 0x6f, 0x72,
0x20, 0x31, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64,
0x73, 0x65, 0x74, 0x2e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x28, 0x30,
0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67,
0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x6f, 0x72, 0x69, 0x67,
0x69, 0x6e, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74,
0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68,
0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68,
0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x72, 0x65, 0x6e, 0x64, 0x65,
0x72, 0x54, 0x6f, 0x28, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x29, 0x20,
0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73,
0x2e, 0x68, 0x61, 0x73, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x28, 0x29,
0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63,
0x73, 0x2e, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x28, 0x29, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x28, 0x29,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20,
0x72, 0x54, 0x6f, 0x28, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x64, 0x72, 0x61,
0x77, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65,
0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69,
0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68,
0x69, 0x63, 0x73, 0x2e, 0x68, 0x61, 0x73, 0x57, 0x69, 0x6e, 0x64, 0x6f,
0x77, 0x28, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x6d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69,
0x63, 0x73, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x28, 0x29,
0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a,
0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x65, 0x72, 0x72, 0x6f,
0x72, 0x28, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x2c, 0x20, 0x65, 0x72,
0x72, 0x29, 0x0a, 0x20, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x27,
0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72,
0x5c, 0x6e, 0x5c, 0x6e, 0x27, 0x20, 0x2e, 0x2e, 0x20, 0x65, 0x72, 0x72,
0x2c, 0x20, 0x30, 0x29, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x2d, 0x2d,
0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x73,
0x20, 0x75, 0x70, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x72, 0x69,
0x6e, 0x67, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x20,
0x62, 0x79, 0x20, 0x6c, 0x75, 0x61, 0x78, 0x5f, 0x67, 0x65, 0x74, 0x73,
0x74, 0x61, 0x63, 0x6b, 0x20, 0x73, 0x6f, 0x20, 0x69, 0x74, 0x20, 0x6c,
0x6f, 0x6f, 0x6b, 0x73, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x74, 0x68,
0x65, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x6d, 0x65, 0x73, 0x73,
0x61, 0x67, 0x65, 0x20, 0x70, 0x6c, 0x75, 0x73, 0x20, 0x74, 0x68, 0x65,
0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x72, 0x6f, 0x6d,
0x0a, 0x2d, 0x2d, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67, 0x2e, 0x74, 0x72,
0x61, 0x63, 0x65, 0x62, 0x61, 0x63, 0x6b, 0x28, 0x29, 0x2e, 0x20, 0x54,
0x68, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x73,
0x20, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x6f,
0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x65, 0x77, 0x6c, 0x69, 0x6e,
0x65, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x20, 0x27, 0x73, 0x74,
0x61, 0x63, 0x6b, 0x20, 0x74, 0x72, 0x61, 0x63, 0x65, 0x62, 0x61, 0x63,
0x6b, 0x3a, 0x27, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x61, 0x70, 0x70, 0x65,
0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20, 0x6e, 0x65, 0x77, 0x6c,
0x69, 0x6e, 0x65, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75,
0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x70, 0x6c, 0x69, 0x74,
0x4f, 0x6e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x4c, 0x69, 0x6e, 0x65, 0x28,
0x73, 0x2c, 0x20, 0x74, 0x29, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61,
0x6c, 0x20, 0x61, 0x74, 0x20, 0x3d, 0x20, 0x73, 0x3a, 0x72, 0x65, 0x76,
0x65, 0x72, 0x73, 0x65, 0x28, 0x29, 0x3a, 0x66, 0x69, 0x6e, 0x64, 0x28,
0x74, 0x3a, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x28, 0x29, 0x29,
0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65,
0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20,
0x73, 0x6c, 0x65, 0x6e, 0x20, 0x3d, 0x20, 0x23, 0x73, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x61, 0x74, 0x20, 0x3d, 0x20, 0x28, 0x23, 0x73, 0x20, 0x2d,
0x20, 0x61, 0x74, 0x20, 0x2d, 0x20, 0x23, 0x74, 0x20, 0x2b, 0x20, 0x32,
0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e,
0x20, 0x73, 0x3a, 0x73, 0x75, 0x62, 0x28, 0x31, 0x2c, 0x20, 0x61, 0x74,
0x2d, 0x32, 0x29, 0x2c, 0x20, 0x73, 0x3a, 0x73, 0x75, 0x62, 0x28, 0x61,
0x74, 0x2c, 0x73, 0x6c, 0x65, 0x6e, 0x29, 0x20, 0x2e, 0x2e, 0x20, 0x27,
0x5c, 0x6e, 0x27, 0x0a, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x73, 0x2c,
0x20, 0x27, 0x27, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x65, 0x6e,
0x64, 0x0a, 0x0a, 0x2d, 0x2d, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x20, 0x77,
0x69, 0x6c, 0x6c, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x74, 0x68, 0x69, 0x73,
0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x69, 0x6e,
0x20, 0x69, 0x74, 0x73, 0x20, 0x6f, 0x77, 0x6e, 0x20, 0x63, 0x6f, 0x72,
0x6f, 0x75, 0x74, 0x69, 0x6e, 0x65, 0x0a, 0x72, 0x65, 0x74, 0x75, 0x72,
0x6e, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29,
0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x72, 0x72,
0x6f, 0x72, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x66, 0x61, 0x6c, 0x73, 0x65,
0x20, 0x2d, 0x2d, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x65, 0x72, 0x72,
0x68, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x6f, 0x6e, 0x6c,
0x79, 0x20, 0x62, 0x65, 0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20,
0x6f, 0x6e, 0x63, 0x65, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x6e,
0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x65, 0x2c, 0x20, 0x74, 0x62, 0x29,
0x20, 0x2d, 0x2d, 0x20, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x20,
0x66, 0x6f, 0x72, 0x20, 0x65, 0x72, 0x72, 0x68, 0x61, 0x6e, 0x64, 0x20,
0x74, 0x6f, 0x20, 0x65, 0x6e, 0x73, 0x75, 0x72, 0x65, 0x20, 0x69, 0x74,
0x20, 0x69, 0x73, 0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x63, 0x61, 0x6c,
0x6c, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x63, 0x65, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x20, 0x61, 0x62, 0x6f, 0x72, 0x74, 0x63, 0x6c, 0x65,
0x61, 0x6e, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72,
0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6e,
0x6f, 0x74, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x74,
0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x72,
0x72, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x74, 0x72, 0x75, 0x65,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x6d, 0x61, 0x74,
0x68, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x6d, 0x61, 0x74, 0x68, 0x2e, 0x64,
0x72, 0x61, 0x69, 0x6e, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65,
0x6e, 0x64, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x65, 0x6e, 0x64,
0x0a, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c,
0x6f, 0x76, 0x72, 0x2e, 0x6d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x29,
0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68,
0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20,
0x2d, 0x2d, 0x20, 0x4f, 0x6e, 0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x73,
0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x2c, 0x20, 0x68, 0x65, 0x61, 0x64,
0x73, 0x65, 0x74, 0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x20, 0x77,
0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x64, 0x69, 0x73, 0x61, 0x62,
0x6c, 0x65, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61,
0x6c, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x20, 0x3d, 0x20,
0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74,
0x2e, 0x67, 0x65, 0x74, 0x4d, 0x69, 0x72, 0x72, 0x6f, 0x72, 0x54, 0x65,
0x78, 0x74, 0x75, 0x72, 0x65, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x69, 0x66, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x20, 0x74,
0x68, 0x65, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x20, 0x4f, 0x6e,
0x20, 0x73, 0x6f, 0x6d, 0x65, 0x20, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72,
0x73, 0x2c, 0x20, 0x74, 0x65, 0x78, 0x74, 0x75, 0x72, 0x65, 0x20, 0x69,
0x73, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x64, 0x69,
0x72, 0x65, 0x63, 0x74, 0x6c, 0x79, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68,
0x65, 0x20, 0x77, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70,
0x68, 0x69, 0x63, 0x73, 0x2e, 0x66, 0x69, 0x6c, 0x6c, 0x28, 0x74, 0x65,
0x78, 0x74, 0x75, 0x72, 0x65, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65,
0x6e, 0x64, 0x0a, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68,
0x69, 0x63, 0x73, 0x2e, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x28, 0x29, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x64, 0x72, 0x61,
0x77, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x65, 0x6e,
0x64, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74,
0x54, 0x72, 0x61, 0x63, 0x65, 0x62, 0x61, 0x63, 0x6b, 0x28, 0x73, 0x29,
0x0a, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x73, 0x3a,
0x67, 0x73, 0x75, 0x62, 0x28, 0x27, 0x5c, 0x6e, 0x5b, 0x5e, 0x5c, 0x6e,
0x5d, 0x2b, 0x24, 0x27, 0x2c, 0x20, 0x27, 0x27, 0x29, 0x3a, 0x67, 0x73,
0x75, 0x62, 0x28, 0x27, 0x5c, 0x74, 0x27, 0x2c, 0x20, 0x27, 0x27, 0x29,
0x3a, 0x67, 0x73, 0x75, 0x62, 0x28, 0x27, 0x73, 0x74, 0x61, 0x63, 0x6b,
0x20, 0x74, 0x72, 0x61, 0x63, 0x65, 0x62, 0x61, 0x63, 0x6b, 0x27, 0x2c,
0x20, 0x27, 0x5c, 0x6e, 0x53, 0x74, 0x61, 0x63, 0x6b, 0x27, 0x29, 0x0a,
0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x65, 0x72, 0x72, 0x68, 0x61,
0x6e, 0x64, 0x28, 0x65, 0x2c, 0x20, 0x74, 0x62, 0x29, 0x20, 0x6f, 0x72,
0x6e, 0x64, 0x28, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2c, 0x20,
0x74, 0x72, 0x61, 0x63, 0x65, 0x62, 0x61, 0x63, 0x6b, 0x29, 0x0a, 0x20,
0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x3d, 0x20, 0x74,
0x6f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x6d, 0x65, 0x73, 0x73,
0x61, 0x67, 0x65, 0x29, 0x0a, 0x20, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61,
0x67, 0x65, 0x20, 0x3d, 0x20, 0x27, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x3a,
0x5c, 0x6e, 0x27, 0x20, 0x2e, 0x2e, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61,
0x67, 0x65, 0x20, 0x2e, 0x2e, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74,
0x54, 0x72, 0x61, 0x63, 0x65, 0x62, 0x61, 0x63, 0x6b, 0x28, 0x74, 0x72,
0x61, 0x63, 0x65, 0x62, 0x61, 0x63, 0x6b, 0x20, 0x6f, 0x72, 0x20, 0x64,
0x65, 0x62, 0x75, 0x67, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x62, 0x61,
0x63, 0x6b, 0x28, 0x27, 0x27, 0x2c, 0x20, 0x34, 0x29, 0x29, 0x0a, 0x20,
0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x6d, 0x65, 0x73, 0x73, 0x61,
0x67, 0x65, 0x29, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74,
0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69,
0x63, 0x73, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75,
0x72, 0x6e, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28,
0x29, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x31, 0x20, 0x65,
0x6e, 0x64, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x72,
0x65, 0x73, 0x65, 0x74, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x73,
0x65, 0x74, 0x42, 0x61, 0x63, 0x6b, 0x67, 0x72, 0x6f, 0x75, 0x6e, 0x64,
0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x28, 0x2e, 0x31, 0x30, 0x35, 0x2c, 0x20,
0x2e, 0x30, 0x39, 0x38, 0x2c, 0x20, 0x2e, 0x31, 0x33, 0x37, 0x29, 0x0a,
0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68,
0x69, 0x63, 0x73, 0x2e, 0x73, 0x65, 0x74, 0x43, 0x6f, 0x6c, 0x6f, 0x72,
0x28, 0x2e, 0x38, 0x36, 0x33, 0x2c, 0x20, 0x2e, 0x38, 0x36, 0x33, 0x2c,
0x20, 0x2e, 0x38, 0x36, 0x33, 0x29, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x63,
0x61, 0x6c, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x20, 0x3d, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e,
0x67, 0x65, 0x74, 0x46, 0x6f, 0x6e, 0x74, 0x28, 0x29, 0x0a, 0x20, 0x20,
0x66, 0x6f, 0x6e, 0x74, 0x3a, 0x73, 0x65, 0x74, 0x46, 0x6c, 0x69, 0x70,
0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x28, 0x66, 0x61, 0x6c, 0x73,
0x65, 0x29, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x70,
0x69, 0x78, 0x65, 0x6c, 0x44, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x20,
0x3d, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x3a, 0x67, 0x65, 0x74, 0x50, 0x69,
0x78, 0x65, 0x6c, 0x44, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x28, 0x29,
0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x77, 0x69, 0x64,
0x74, 0x68, 0x20, 0x3d, 0x20, 0x66, 0x6f, 0x6e, 0x74, 0x3a, 0x67, 0x65,
0x74, 0x57, 0x69, 0x64, 0x74, 0x68, 0x28, 0x6d, 0x65, 0x73, 0x73, 0x61,
0x67, 0x65, 0x2c, 0x20, 0x2e, 0x35, 0x35, 0x20, 0x2a, 0x20, 0x70, 0x69,
0x78, 0x65, 0x6c, 0x44, 0x65, 0x6e, 0x73, 0x69, 0x74, 0x79, 0x29, 0x0a,
0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63,
0x74, 0x69, 0x6f, 0x6e, 0x20, 0x72, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x28,
0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67,
0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x69, 0x6e,
0x74, 0x28, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2c, 0x20, 0x2d,
0x77, 0x69, 0x64, 0x74, 0x68, 0x20, 0x2f, 0x20, 0x32, 0x2c, 0x20, 0x30,
0x2c, 0x20, 0x2d, 0x32, 0x30, 0x2c, 0x20, 0x31, 0x2c, 0x20, 0x30, 0x2c,
0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x30, 0x2c, 0x20, 0x2e, 0x35,
0x35, 0x20, 0x2a, 0x20, 0x70, 0x69, 0x78, 0x65, 0x6c, 0x44, 0x65, 0x6e,
0x73, 0x69, 0x74, 0x79, 0x2c, 0x20, 0x27, 0x6c, 0x65, 0x66, 0x74, 0x27,
0x29, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x72, 0x65,
0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72,
0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x75, 0x6d, 0x70, 0x28,
0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x61,
0x6d, 0x65, 0x2c, 0x20, 0x61, 0x20, 0x69, 0x6e, 0x20, 0x6c, 0x6f, 0x76,
0x72, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x6f, 0x6c, 0x6c,
0x28, 0x29, 0x20, 0x64, 0x6f, 0x20, 0x69, 0x66, 0x20, 0x6e, 0x61, 0x6d,
0x65, 0x20, 0x3d, 0x3d, 0x20, 0x27, 0x71, 0x75, 0x69, 0x74, 0x27, 0x20,
0x74, 0x68, 0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20,
0x61, 0x20, 0x6f, 0x72, 0x20, 0x31, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x65,
0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x75, 0x70, 0x64, 0x61,
0x74, 0x65, 0x28, 0x30, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e,
0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x68, 0x65, 0x61,
0x64, 0x73, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x68, 0x65, 0x61, 0x64, 0x73, 0x65, 0x74, 0x2e, 0x72,
0x65, 0x6e, 0x64, 0x65, 0x72, 0x54, 0x6f, 0x28, 0x72, 0x65, 0x6e, 0x64,
0x65, 0x72, 0x29, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x69, 0x66, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61, 0x70,
0x68, 0x69, 0x63, 0x73, 0x2e, 0x68, 0x61, 0x73, 0x57, 0x69, 0x6e, 0x64,
0x6f, 0x77, 0x28, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72, 0x61,
0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x63, 0x6c, 0x65, 0x61, 0x72, 0x28,
0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x6e, 0x64,
0x65, 0x72, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x67, 0x72,
0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x65, 0x73, 0x65,
0x6e, 0x74, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x65,
0x6e, 0x64, 0x0a, 0x0a, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64,
0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64,
0x2c, 0x20, 0x65, 0x72, 0x72, 0x29, 0x0a, 0x20, 0x20, 0x65, 0x72, 0x72,
0x6f, 0x72, 0x28, 0x27, 0x54, 0x68, 0x72, 0x65, 0x61, 0x64, 0x20, 0x65,
0x72, 0x72, 0x6f, 0x72, 0x5c, 0x6e, 0x5c, 0x6e, 0x27, 0x20, 0x2e, 0x2e,
0x20, 0x65, 0x72, 0x72, 0x2c, 0x20, 0x30, 0x29, 0x0a, 0x65, 0x6e, 0x64,
0x0a, 0x0a, 0x2d, 0x2d, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x73, 0x70,
0x6c, 0x69, 0x74, 0x73, 0x20, 0x75, 0x70, 0x20, 0x74, 0x68, 0x65, 0x20,
0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72,
0x6e, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x6c, 0x75, 0x61, 0x78, 0x5f,
0x67, 0x65, 0x74, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x20, 0x73, 0x6f, 0x20,
0x69, 0x74, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x73, 0x20, 0x6c, 0x69, 0x6b,
0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20,
0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x20, 0x70, 0x6c, 0x75, 0x73,
0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20,
0x66, 0x72, 0x6f, 0x6d, 0x0a, 0x2d, 0x2d, 0x20, 0x64, 0x65, 0x62, 0x75,
0x67, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x62, 0x61, 0x63, 0x6b, 0x28,
0x29, 0x2e, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c,
0x75, 0x64, 0x65, 0x73, 0x20, 0x73, 0x70, 0x6c, 0x69, 0x74, 0x74, 0x69,
0x6e, 0x67, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x65,
0x77, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65,
0x20, 0x27, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x20, 0x74, 0x72, 0x61, 0x63,
0x65, 0x62, 0x61, 0x63, 0x6b, 0x3a, 0x27, 0x20, 0x61, 0x6e, 0x64, 0x20,
0x61, 0x70, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x61, 0x20,
0x6e, 0x65, 0x77, 0x6c, 0x69, 0x6e, 0x65, 0x0a, 0x6c, 0x6f, 0x63, 0x61,
0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73,
0x70, 0x6c, 0x69, 0x74, 0x4f, 0x6e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x4c,
0x69, 0x6e, 0x65, 0x28, 0x73, 0x2c, 0x20, 0x74, 0x29, 0x0a, 0x20, 0x20,
0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x61, 0x74, 0x20, 0x3d, 0x20, 0x73,
0x3a, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x28, 0x29, 0x3a, 0x66,
0x69, 0x6e, 0x64, 0x28, 0x74, 0x3a, 0x72, 0x65, 0x76, 0x65, 0x72, 0x73,
0x65, 0x28, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x69, 0x66, 0x20, 0x61, 0x74,
0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f,
0x63, 0x61, 0x6c, 0x20, 0x73, 0x6c, 0x65, 0x6e, 0x20, 0x3d, 0x20, 0x23,
0x73, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x61, 0x74, 0x20, 0x3d, 0x20, 0x28,
0x23, 0x73, 0x20, 0x2d, 0x20, 0x61, 0x74, 0x20, 0x2d, 0x20, 0x23, 0x74,
0x20, 0x2b, 0x20, 0x32, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65,
0x74, 0x75, 0x72, 0x6e, 0x20, 0x73, 0x3a, 0x73, 0x75, 0x62, 0x28, 0x31,
0x2c, 0x20, 0x61, 0x74, 0x2d, 0x32, 0x29, 0x2c, 0x20, 0x73, 0x3a, 0x73,
0x75, 0x62, 0x28, 0x61, 0x74, 0x2c, 0x73, 0x6c, 0x65, 0x6e, 0x29, 0x20,
0x2e, 0x2e, 0x20, 0x27, 0x5c, 0x6e, 0x27, 0x0a, 0x20, 0x20, 0x65, 0x6c,
0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72,
0x6e, 0x20, 0x73, 0x2c, 0x20, 0x27, 0x27, 0x0a, 0x20, 0x20, 0x65, 0x6e,
0x64, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x2d, 0x2d, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x72, 0x75, 0x6e, 0x20,
0x74, 0x68, 0x69, 0x73, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x20, 0x69, 0x6e, 0x20, 0x69, 0x74, 0x73, 0x20, 0x6f, 0x77, 0x6e,
0x20, 0x63, 0x6f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x65, 0x0a, 0x72,
0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x3d, 0x20, 0x66,
0x61, 0x6c, 0x73, 0x65, 0x20, 0x2d, 0x2d, 0x20, 0x6c, 0x6f, 0x76, 0x72,
0x2e, 0x65, 0x72, 0x72, 0x68, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x79,
0x20, 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x62, 0x65, 0x20, 0x63, 0x61, 0x6c,
0x6c, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x63, 0x65, 0x0a, 0x20, 0x20, 0x6c,
0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f,
0x6e, 0x20, 0x6f, 0x6e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x65, 0x2c,
0x20, 0x74, 0x62, 0x29, 0x20, 0x2d, 0x2d, 0x20, 0x77, 0x72, 0x61, 0x70,
0x70, 0x65, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x65, 0x72, 0x72, 0x68,
0x61, 0x6e, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x65, 0x6e, 0x73, 0x75, 0x72,
0x65, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x6f, 0x6e, 0x6c, 0x79,
0x20, 0x63, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x6f, 0x6e, 0x63, 0x65,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66,
0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x62, 0x6f, 0x72,
0x74, 0x63, 0x6c, 0x65, 0x61, 0x6e, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x31, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72,
0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x65, 0x64, 0x20, 0x3d, 0x20,
0x74, 0x72, 0x75, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72,
0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x65,
0x72, 0x72, 0x68, 0x61, 0x6e, 0x64, 0x28, 0x65, 0x2c, 0x20, 0x74, 0x62,
0x29, 0x20, 0x6f, 0x72, 0x20, 0x61, 0x62, 0x6f, 0x72, 0x74, 0x63, 0x6c,
0x65, 0x61, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74,
0x28, 0x27, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x6f, 0x63, 0x63, 0x75,
0x72, 0x72, 0x65, 0x64, 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x74,
0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x69, 0x73,
0x70, 0x6c, 0x61, 0x79, 0x20, 0x61, 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72,
0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x3a, 0x5c, 0x6e, 0x27, 0x20, 0x2e,
0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x6f,
0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x28, 0x65, 0x29, 0x20, 0x2e, 0x2e,
0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65,
0x62, 0x61, 0x63, 0x6b, 0x28, 0x74, 0x62, 0x20, 0x6f, 0x72, 0x20, 0x64,
0x65, 0x62, 0x75, 0x67, 0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x62, 0x61,
0x63, 0x6b, 0x28, 0x27, 0x27, 0x2c, 0x20, 0x32, 0x29, 0x29, 0x29, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e,
0x20, 0x61, 0x62, 0x6f, 0x72, 0x74, 0x63, 0x6c, 0x65, 0x61, 0x6e, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x27, 0x45, 0x72,
0x72, 0x6f, 0x72, 0x20, 0x6f, 0x63, 0x63, 0x75, 0x72, 0x72, 0x65, 0x64,
0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x72, 0x79, 0x69, 0x6e,
0x67, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79,
0x20, 0x61, 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x65, 0x72, 0x72,
0x6f, 0x72, 0x3a, 0x5c, 0x6e, 0x27, 0x20, 0x2e, 0x2e, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x74, 0x6f, 0x73, 0x74, 0x72, 0x69,
0x6e, 0x67, 0x28, 0x65, 0x29, 0x20, 0x2e, 0x2e, 0x20, 0x66, 0x6f, 0x72,
0x6d, 0x61, 0x74, 0x54, 0x72, 0x61, 0x63, 0x65, 0x62, 0x61, 0x63, 0x6b,
0x28, 0x74, 0x62, 0x20, 0x6f, 0x72, 0x20, 0x64, 0x65, 0x62, 0x75, 0x67,
0x2e, 0x74, 0x72, 0x61, 0x63, 0x65, 0x62, 0x61, 0x63, 0x6b, 0x28, 0x27,
0x27, 0x2c, 0x20, 0x32, 0x29, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x61, 0x62, 0x6f,
0x72, 0x74, 0x63, 0x6c, 0x65, 0x61, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x20,
0x20, 0x2d, 0x2d, 0x20, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x73,
0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x62, 0x6f, 0x6f, 0x74, 0x20, 0x61,
0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x72, 0x75, 0x6e, 0x2e,
0x0a, 0x20, 0x20, 0x2d, 0x2d, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e,
0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x61, 0x66, 0x74, 0x65,
0x72, 0x77, 0x61, 0x72, 0x64, 0x2c, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20,
0x62, 0x65, 0x20, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x6c, 0x6f,
0x76, 0x72, 0x2e, 0x72, 0x75, 0x6e, 0x27, 0x73, 0x20, 0x70, 0x65, 0x72,
0x2d, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20,
0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x65, 0x72,
0x72, 0x68, 0x61, 0x6e, 0x64, 0x2e, 0x0a, 0x20, 0x20, 0x6c, 0x6f, 0x63,
0x61, 0x6c, 0x20, 0x5f, 0x2c, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e,
0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x78, 0x70, 0x63,
0x61, 0x6c, 0x6c, 0x28, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x62, 0x6f, 0x6f,
0x74, 0x2c, 0x20, 0x6f, 0x6e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x29, 0x0a,
0x0a, 0x20, 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x72, 0x75,
0x65, 0x20, 0x64, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20,
0x74, 0x79, 0x70, 0x65, 0x28, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x20, 0x3d, 0x3d, 0x20, 0x27, 0x73,
0x74, 0x72, 0x69, 0x6e, 0x67, 0x27, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20,
0x2d, 0x2d, 0x20, 0x4c, 0x75, 0x61, 0x4a, 0x49, 0x54, 0x20, 0x72, 0x65,
0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x61, 0x20, 0x66, 0x69, 0x78, 0x65,
0x64, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x66, 0x20,
0x61, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x6f, 0x63, 0x63,
0x75, 0x72, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x6e, 0x20, 0x78, 0x70,
0x63, 0x61, 0x6c, 0x6c, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x68,
0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x27, 0x45, 0x72, 0x72, 0x6f,
0x72, 0x20, 0x6f, 0x63, 0x63, 0x75, 0x72, 0x72, 0x65, 0x64, 0x20, 0x77,
0x68, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20,
0x74, 0x6f, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x20, 0x61,
0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72,
0x2e, 0x27, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65,
0x74, 0x75, 0x72, 0x6e, 0x20, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65,
0x6e, 0x64, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61,
0x6c, 0x20, 0x6f, 0x6b, 0x2c, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74,
0x20, 0x3d, 0x20, 0x78, 0x70, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x63, 0x6f,
0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x65, 0x6e,
0x64, 0x0a, 0x0a, 0x20, 0x20, 0x2d, 0x2d, 0x20, 0x45, 0x78, 0x65, 0x63,
0x75, 0x74, 0x65, 0x73, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x62, 0x6f,
0x6f, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x72, 0x75, 0x6e, 0x2e, 0x0a, 0x20, 0x20, 0x2d, 0x2d, 0x20, 0x63, 0x6f,
0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20,
0x6f, 0x6e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x29, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x69, 0x66, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x61,
0x6e, 0x64, 0x20, 0x6f, 0x6b, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x72,
0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74,
0x20, 0x2d, 0x2d, 0x20, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x69,
0x73, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20, 0x72, 0x65, 0x74, 0x75,
0x72, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x66, 0x75, 0x6e, 0x63,
0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e,
0x20, 0x69, 0x74, 0x2e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73,
0x65, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6f, 0x6b, 0x20, 0x74,
0x68, 0x65, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c,
0x74, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x2d, 0x2d, 0x20, 0x52, 0x65, 0x73,
0x75, 0x6c, 0x74, 0x20, 0x69, 0x73, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65,
0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x79,
0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c,
0x65, 0x72, 0x2e, 0x20, 0x4d, 0x61, 0x6b, 0x65, 0x20, 0x69, 0x74, 0x20,
0x74, 0x68, 0x65, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x65, 0x72, 0x72, 0x6f,
0x72, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x2e, 0x0a, 0x0a,
0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x78,
0x74, 0x65, 0x72, 0x6e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x3d, 0x20,
0x63, 0x6f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e, 0x65, 0x2e, 0x79, 0x69,
0x65, 0x6c, 0x64, 0x28, 0x29, 0x20, 0x2d, 0x2d, 0x20, 0x52, 0x65, 0x74,
0x75, 0x72, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x20,
0x74, 0x6f, 0x20, 0x43, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x0a, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e,
0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x2d,
0x2d, 0x20, 0x41, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x2d, 0x72, 0x65, 0x70,
0x6f, 0x72, 0x74, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x6f, 0x63,
0x63, 0x75, 0x72, 0x72, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68,
0x65, 0x20, 0x43, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x65, 0x72, 0x72,
0x6f, 0x72, 0x70, 0x61, 0x72, 0x74, 0x2c, 0x20, 0x74, 0x72, 0x61, 0x63,
0x65, 0x70, 0x61, 0x72, 0x74, 0x20, 0x3d, 0x20, 0x73, 0x70, 0x6c, 0x69,
0x74, 0x4f, 0x6e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x4c, 0x69, 0x6e, 0x65,
0x28, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x72, 0x72, 0x6f, 0x72,
0x2c, 0x20, 0x27, 0x73, 0x74, 0x61, 0x63, 0x6b, 0x20, 0x74, 0x72, 0x61,
0x63, 0x65, 0x62, 0x61, 0x63, 0x6b, 0x3a, 0x27, 0x29, 0x0a, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x6f, 0x6e, 0x65, 0x72, 0x72,
0x6f, 0x72, 0x28, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x70, 0x61, 0x72, 0x74,
0x2c, 0x20, 0x74, 0x72, 0x61, 0x63, 0x65, 0x70, 0x61, 0x72, 0x74, 0x29,
0x20, 0x2d, 0x2d, 0x20, 0x53, 0x77, 0x69, 0x74, 0x63, 0x68, 0x20, 0x63,
0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20,
0x74, 0x6f, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x65, 0x72, 0x72, 0x68,
0x61, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a,
0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x65, 0x6e, 0x64, 0x0a
0x61, 0x66, 0x74, 0x65, 0x72, 0x77, 0x61, 0x72, 0x64, 0x2c, 0x20, 0x77,
0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x65, 0x69, 0x74, 0x68, 0x65,
0x72, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e, 0x72, 0x75, 0x6e, 0x27, 0x73,
0x20, 0x70, 0x65, 0x72, 0x2d, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x20, 0x66,
0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2c, 0x20, 0x6f, 0x72, 0x20,
0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x6f,
0x66, 0x20, 0x65, 0x72, 0x72, 0x68, 0x61, 0x6e, 0x64, 0x2e, 0x0a, 0x20,
0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x5f, 0x2c, 0x20, 0x63, 0x6f,
0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d,
0x20, 0x78, 0x70, 0x63, 0x61, 0x6c, 0x6c, 0x28, 0x6c, 0x6f, 0x76, 0x72,
0x2e, 0x62, 0x6f, 0x6f, 0x74, 0x2c, 0x20, 0x6f, 0x6e, 0x65, 0x72, 0x72,
0x6f, 0x72, 0x29, 0x0a, 0x0a, 0x20, 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65,
0x20, 0x74, 0x72, 0x75, 0x65, 0x20, 0x64, 0x6f, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x69, 0x66, 0x20, 0x74, 0x79, 0x70, 0x65, 0x28, 0x63, 0x6f, 0x6e,
0x74, 0x69, 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x29, 0x20, 0x3d,
0x3d, 0x20, 0x27, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x27, 0x20, 0x74,
0x68, 0x65, 0x6e, 0x20, 0x2d, 0x2d, 0x20, 0x4c, 0x75, 0x61, 0x4a, 0x49,
0x54, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x61, 0x20,
0x66, 0x69, 0x78, 0x65, 0x64, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
0x20, 0x69, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72,
0x20, 0x6f, 0x63, 0x63, 0x75, 0x72, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x61,
0x6e, 0x20, 0x78, 0x70, 0x63, 0x61, 0x6c, 0x6c, 0x20, 0x65, 0x72, 0x72,
0x6f, 0x72, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x28, 0x27,
0x45, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x6f, 0x63, 0x63, 0x75, 0x72, 0x72,
0x65, 0x64, 0x20, 0x77, 0x68, 0x69, 0x6c, 0x65, 0x20, 0x74, 0x72, 0x79,
0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x64, 0x69, 0x73, 0x70, 0x6c,
0x61, 0x79, 0x20, 0x61, 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x65,
0x72, 0x72, 0x6f, 0x72, 0x2e, 0x27, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x31, 0x0a, 0x20,
0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6f, 0x6b, 0x2c, 0x20, 0x72, 0x65,
0x73, 0x75, 0x6c, 0x74, 0x20, 0x3d, 0x20, 0x78, 0x70, 0x63, 0x61, 0x6c,
0x6c, 0x28, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x2c, 0x20, 0x6f, 0x6e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x29,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x72, 0x65, 0x73, 0x75,
0x6c, 0x74, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6f, 0x6b, 0x20, 0x74, 0x68,
0x65, 0x6e, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x72, 0x65,
0x73, 0x75, 0x6c, 0x74, 0x20, 0x2d, 0x2d, 0x20, 0x52, 0x65, 0x73, 0x75,
0x6c, 0x74, 0x20, 0x69, 0x73, 0x20, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x20,
0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20,
0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x20, 0x52, 0x65,
0x74, 0x75, 0x72, 0x6e, 0x20, 0x69, 0x74, 0x2e, 0x0a, 0x20, 0x20, 0x20,
0x20, 0x65, 0x6c, 0x73, 0x65, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20,
0x6f, 0x6b, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x74,
0x69, 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x72,
0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x2d, 0x2d,
0x20, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x20, 0x69, 0x73, 0x20, 0x76,
0x61, 0x6c, 0x75, 0x65, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x65,
0x64, 0x20, 0x62, 0x79, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x68,
0x61, 0x6e, 0x64, 0x6c, 0x65, 0x72, 0x2e, 0x20, 0x4d, 0x61, 0x6b, 0x65,
0x20, 0x69, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6e, 0x65, 0x77, 0x20,
0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x68, 0x61, 0x6e, 0x64, 0x6c, 0x65,
0x72, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61,
0x6c, 0x20, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x65, 0x72, 0x72, 0x6f,
0x72, 0x20, 0x3d, 0x20, 0x63, 0x6f, 0x72, 0x6f, 0x75, 0x74, 0x69, 0x6e,
0x65, 0x2e, 0x79, 0x69, 0x65, 0x6c, 0x64, 0x28, 0x29, 0x20, 0x2d, 0x2d,
0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x74,
0x72, 0x6f, 0x6c, 0x20, 0x74, 0x6f, 0x20, 0x43, 0x20, 0x63, 0x6f, 0x64,
0x65, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x65, 0x78,
0x74, 0x65, 0x72, 0x6e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, 0x74, 0x68,
0x65, 0x6e, 0x20, 0x2d, 0x2d, 0x20, 0x41, 0x20, 0x6d, 0x75, 0x73, 0x74,
0x2d, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x65, 0x72, 0x72, 0x6f,
0x72, 0x20, 0x6f, 0x63, 0x63, 0x75, 0x72, 0x72, 0x65, 0x64, 0x20, 0x69,
0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x43, 0x20, 0x63, 0x6f, 0x64, 0x65,
0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x70, 0x61, 0x72, 0x74, 0x2c, 0x20,
0x74, 0x72, 0x61, 0x63, 0x65, 0x70, 0x61, 0x72, 0x74, 0x20, 0x3d, 0x20,
0x73, 0x70, 0x6c, 0x69, 0x74, 0x4f, 0x6e, 0x4c, 0x61, 0x62, 0x65, 0x6c,
0x4c, 0x69, 0x6e, 0x65, 0x28, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x65,
0x72, 0x72, 0x6f, 0x72, 0x2c, 0x20, 0x27, 0x73, 0x74, 0x61, 0x63, 0x6b,
0x20, 0x74, 0x72, 0x61, 0x63, 0x65, 0x62, 0x61, 0x63, 0x6b, 0x3a, 0x27,
0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6e, 0x74,
0x69, 0x6e, 0x75, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x6f,
0x6e, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x28, 0x65, 0x72, 0x72, 0x6f, 0x72,
0x70, 0x61, 0x72, 0x74, 0x2c, 0x20, 0x74, 0x72, 0x61, 0x63, 0x65, 0x70,
0x61, 0x72, 0x74, 0x29, 0x20, 0x2d, 0x2d, 0x20, 0x53, 0x77, 0x69, 0x74,
0x63, 0x68, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x6c, 0x6f, 0x76, 0x72, 0x2e,
0x65, 0x72, 0x72, 0x68, 0x61, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20,
0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x65, 0x6e,
0x64, 0x0a
};
unsigned int boot_lua_len = 8662;
unsigned int boot_lua_len = 8738;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff