text:
/*
 * oculusdevice.cpp
 *
 *  Created on: Jul 03, 2013
 *      Author: Bjorn Blissing
 *
 *  MSAA support added: Sep 17, 2015
 *      Author: Chris Denham
 */

#include "oculusdevice.h"

#ifdef _WIN32
	#include <Windows.h>
#endif

#include <osg/Geometry>
#include <osgViewer/Renderer>
#include <osgViewer/GraphicsWindow>

#ifndef GL_TEXTURE_MAX_LEVEL
	#define GL_TEXTURE_MAX_LEVEL 0x813D
#endif

static const OSG_GLExtensions* getGLExtensions(const osg::State& state)
{
#if(OSG_VERSION_GREATER_OR_EQUAL(3, 4, 0))
	return state.get<osg::GLExtensions>();
#else
	return osg::FBOExtensions::instance(state.getContextID(), true);
#endif
}

static const OSG_Texture_Extensions* getTextureExtensions(const osg::State& state)
{
#if(OSG_VERSION_GREATER_OR_EQUAL(3, 4, 0))
	return state.get<osg::GLExtensions>();
#else
	return osg::Texture::getExtensions(state.getContextID(), true);
#endif
}

static osg::FrameBufferObject* getFrameBufferObject(osg::RenderInfo& renderInfo)
{
	osg::Camera* camera = renderInfo.getCurrentCamera();
	osgViewer::Renderer* camRenderer = (dynamic_cast<osgViewer::Renderer*>(camera->getRenderer()));

	if (camRenderer != nullptr)
	{
		osgUtil::SceneView* sceneView = camRenderer->getSceneView(0);

		if (sceneView != nullptr)
		{
			osgUtil::RenderStage* renderStage = sceneView->getRenderStage();

			if (renderStage != nullptr)
			{
				return renderStage->getFrameBufferObject();
			}
		}
	}

	return nullptr;
}

void OculusPreDrawCallback::operator()(osg::RenderInfo& renderInfo) const
{
	m_textureBuffer->onPreRender(renderInfo);
}

void OculusPostDrawCallback::operator()(osg::RenderInfo& renderInfo) const
{
	m_textureBuffer->onPostRender(renderInfo);
}

/* Public functions */
OculusTextureBuffer::OculusTextureBuffer(const ovrSession& session, osg::ref_ptr<osg::State> state, const ovrSizei& size, int samples) : m_session(session),
	m_textureSet(nullptr),
	m_colorBuffer(nullptr),
	m_depthBuffer(nullptr),
	m_textureSize(osg::Vec2i(size.w, size.h)),
	m_Oculus_FBO(0),
	m_MSAA_FBO(0),
	m_MSAA_ColorTex(0),
	m_MSAA_DepthTex(0),
	m_samples(samples)
{
	if (samples == 0)
	{
		setup(*state);
	}
	else
	{
		setupMSAA(*state);
	}

}

void OculusTextureBuffer::setup(osg::State& state)
{
	if (ovr_CreateSwapTextureSetGL(m_session, GL_SRGB8_ALPHA8, textureWidth(), textureHeight(), &m_textureSet) == ovrSuccess)
	{
		// Assign textures to OSG textures
		for (int i = 0; i < m_textureSet->TextureCount; ++i)
		{
			ovrGLTexture* tex = reinterpret_cast<ovrGLTexture*>(&m_textureSet->Textures[i]);

			GLuint handle = tex->OGL.TexId;

			osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D();

			osg::ref_ptr<osg::Texture::TextureObject> textureObject = new osg::Texture::TextureObject(texture.get(), handle, GL_TEXTURE_2D);

			textureObject->setAllocated(true);

			texture->setTextureObject(state.getContextID(), textureObject.get());

			texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR);
			texture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR);
			texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
			texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);

			texture->setTextureSize(tex->Texture.Header.TextureSize.w, tex->Texture.Header.TextureSize.h);
			texture->setSourceFormat(GL_SRGB8_ALPHA8);

			// Set the current texture to point to the texture with the index (which will be advanced before drawing)
			if (i == (m_textureSet->CurrentIndex + 1))
			{
				m_colorBuffer = texture;
			}
		}

		osg::notify(osg::DEBUG_INFO) << "Successfully created the swap texture set!" << std::endl;
	}
	else
	{
		osg::notify(osg::WARN) << "Warning: Unable to create swap texture set! " << std::endl;
		return;
	}

	m_depthBuffer = new osg::Texture2D();
	m_depthBuffer->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR);
	m_depthBuffer->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR);
	m_depthBuffer->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
	m_depthBuffer->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
	m_depthBuffer->setSourceFormat(GL_DEPTH_COMPONENT);
	m_depthBuffer->setSourceType(GL_UNSIGNED_INT);
	m_depthBuffer->setInternalFormat(GL_DEPTH_COMPONENT24);
	m_depthBuffer->setTextureWidth(textureWidth());
	m_depthBuffer->setTextureHeight(textureHeight());
	m_depthBuffer->setBorderWidth(0);

}

void OculusTextureBuffer::setupMSAA(osg::State& state)
{
	const OSG_GLExtensions* fbo_ext = getGLExtensions(state);

	if (ovr_CreateSwapTextureSetGL(m_session, GL_SRGB8_ALPHA8, m_textureSize.x(), m_textureSize.y(), &m_textureSet) == ovrSuccess)
	{
		for (int i = 0; i < m_textureSet->TextureCount; ++i)
		{
			ovrGLTexture* tex = reinterpret_cast<ovrGLTexture*>(&m_textureSet->Textures[i]);
			glBindTexture(GL_TEXTURE_2D, tex->OGL.TexId);

			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
		}
	}

	// Create an FBO for output to Oculus swap texture set.
	fbo_ext->glGenFramebuffers(1, &m_Oculus_FBO);

	// Create an FBO for primary render target.
	fbo_ext->glGenFramebuffers(1, &m_MSAA_FBO);

	// We don't want to support MIPMAP so, ensure only level 0 is allowed.
	const int maxTextureLevel = 0;

	const OSG_Texture_Extensions* extensions = getTextureExtensions(state);

	// Create MSAA colour buffer
	glGenTextures(1, &m_MSAA_ColorTex);
	glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_MSAA_ColorTex);
	extensions->glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_samples, GL_RGBA, m_textureSize.x(), m_textureSize.y(), false);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER_ARB);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER_ARB);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAX_LEVEL, maxTextureLevel);

	// Create MSAA depth buffer
	glGenTextures(1, &m_MSAA_DepthTex);
	glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_MSAA_DepthTex);
	extensions->glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_samples, GL_DEPTH_COMPONENT, m_textureSize.x(), m_textureSize.y(), false);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D_MULTISAMPLE, GL_TEXTURE_MAX_LEVEL, maxTextureLevel);
}

void OculusTextureBuffer::onPreRender(osg::RenderInfo& renderInfo)
{
	advanceIndex();

	osg::State& state = *renderInfo.getState();
	const OSG_GLExtensions* fbo_ext = getGLExtensions(state);

	if (m_samples == 0)
	{
		osg::FrameBufferObject* fbo = getFrameBufferObject(renderInfo);

		if (fbo == nullptr)
		{
			return;
		}

		const unsigned int ctx = state.getContextID();
		ovrGLTexture* tex = reinterpret_cast<ovrGLTexture*>(&m_textureSet->Textures[m_textureSet->CurrentIndex]);
		fbo_ext->glBindFramebuffer(GL_FRAMEBUFFER_EXT, fbo->getHandle(ctx));
		fbo_ext->glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tex->OGL.TexId, 0);
		fbo_ext->glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, m_depthBuffer->getTextureObject(state.getContextID())->id(), 0);
	}
	else
	{
		fbo_ext->glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_MSAA_FBO);
		fbo_ext->glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D_MULTISAMPLE, m_MSAA_ColorTex, 0);
		fbo_ext->glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D_MULTISAMPLE, m_MSAA_DepthTex, 0);
	}

}
void OculusTextureBuffer::onPostRender(osg::RenderInfo& renderInfo)
{
	if (m_samples == 0)
	{
		// Nothing to do here if MSAA not being used.
		return;
	}

	osg::State& state = *renderInfo.getState();
	const OSG_GLExtensions* fbo_ext = getGLExtensions(state);

	fbo_ext->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, m_MSAA_FBO);
	fbo_ext->glFramebufferTexture2D(GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D_MULTISAMPLE, m_MSAA_ColorTex, 0);
	fbo_ext->glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0);

	ovrGLTexture* tex = reinterpret_cast<ovrGLTexture*>(&m_textureSet->Textures[m_textureSet->CurrentIndex]);
	fbo_ext->glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, m_Oculus_FBO);
	fbo_ext->glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tex->OGL.TexId, 0);
	fbo_ext->glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0);

	int w = m_textureSize.x();
	int h = m_textureSize.y();
	fbo_ext->glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);

	fbo_ext->glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);

}

void OculusTextureBuffer::destroy()
{
	ovr_DestroySwapTextureSet(m_session, m_textureSet);
}

OculusMirrorTexture::OculusMirrorTexture(ovrSession& session, osg::ref_ptr<osg::State> state, int width, int height) : m_session(session), m_texture(nullptr)
{
	const OSG_GLExtensions* fbo_ext = getGLExtensions(*state);
	ovr_CreateMirrorTextureGL(m_session, GL_SRGB8_ALPHA8, width, height, reinterpret_cast<ovrTexture**>(&m_texture));
	// Configure the mirror read buffer
	fbo_ext->glGenFramebuffers(1, &m_mirrorFBO);
	fbo_ext->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, m_mirrorFBO);
	fbo_ext->glFramebufferTexture2D(GL_READ_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture->OGL.TexId, 0);
	fbo_ext->glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, 0);
	fbo_ext->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, 0);
}

void OculusMirrorTexture::blitTexture(osg::GraphicsContext* gc)
{
	const OSG_GLExtensions* fbo_ext = getGLExtensions(*(gc->getState()));
	// Blit mirror texture to back buffer
	fbo_ext->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, m_mirrorFBO);
	fbo_ext->glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0);
	GLint w = m_texture->OGL.Header.TextureSize.w;
	GLint h = m_texture->OGL.Header.TextureSize.h;
	fbo_ext->glBlitFramebuffer(0, h, w, 0,
							   0, 0, w, h,
							   GL_COLOR_BUFFER_BIT, GL_NEAREST);
	fbo_ext->glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, 0);
}

void OculusMirrorTexture::destroy(const OSG_GLExtensions* fbo_ext)
{
	if (fbo_ext)
	{
		fbo_ext->glDeleteFramebuffers(1, &m_mirrorFBO);
	}

	ovr_DestroyMirrorTexture(m_session, reinterpret_cast<ovrTexture*>(m_texture));
}

/* Public functions */
OculusDevice::OculusDevice(float nearClip, float farClip, const float pixelsPerDisplayPixel, const float worldUnitsPerMetre, const int samples) :
	m_session(nullptr),
	m_hmdDesc(),
	m_pixelsPerDisplayPixel(pixelsPerDisplayPixel),
	m_worldUnitsPerMetre(worldUnitsPerMetre),
	m_mirrorTexture(nullptr),
	m_position(osg::Vec3(0.0f, 0.0f, 0.0f)),
	m_orientation(osg::Quat(0.0f, 0.0f, 0.0f, 1.0f)),
	m_nearClip(nearClip), m_farClip(farClip),
	m_samples(samples)
{
	for (int i = 0; i < 2; i++)
	{
		m_textureBuffer[i] = nullptr;
	}

	ovrGraphicsLuid luid;

	trySetProcessAsHighPriority();

	if (ovr_Initialize(nullptr) != ovrSuccess)
	{
		osg::notify(osg::WARN) << "Warning: Unable to initialize the Oculus library!" << std::endl;
		return;
	}

	// Get first available HMD
	ovrResult result = ovr_Create(&m_session, &luid);

	if (result != ovrSuccess)
	{
		osg::notify(osg::WARN) << "Warning: No device could be found." << std::endl;
		return;
	}

	// Get HMD description
	m_hmdDesc = ovr_GetHmdDesc(m_session);

	// Print information about device
	printHMDDebugInfo();
}

void OculusDevice::createRenderBuffers(osg::ref_ptr<osg::State> state)
{
	// Compute recommended render texture size
	if (m_pixelsPerDisplayPixel > 1.0f)
	{
		osg::notify(osg::WARN) << "Warning: Pixel per display pixel is set to a value higher than 1.0." << std::endl;
	}

	for (int i = 0; i < 2; i++)
	{
		ovrSizei recommenedTextureSize = ovr_GetFovTextureSize(m_session, (ovrEyeType)i, m_hmdDesc.DefaultEyeFov[i], m_pixelsPerDisplayPixel);
		m_textureBuffer[i] = new OculusTextureBuffer(m_session, state, recommenedTextureSize, m_samples);
	}

	int width = screenResolutionWidth() / 2;
	int height = screenResolutionHeight() / 2;
	m_mirrorTexture = new OculusMirrorTexture(m_session, state, width, height);
}

void OculusDevice::init()
{
	initializeEyeRenderDesc();

	calculateEyeAdjustment();

	calculateProjectionMatrices();

	setupLayers();

	// Reset perf hud
	ovr_SetInt(m_session, "PerfHudMode", (int)ovrPerfHud_Off);
}

bool OculusDevice::hmdPresent() const
{
	ovrSessionStatus status;

	if (m_session)
	{
		ovrResult result = ovr_GetSessionStatus(m_session, &status);

		if (result == ovrSuccess)
		{
			return (status.HmdPresent == ovrTrue);
		}
		else
		{
			ovrErrorInfo error;
			ovr_GetLastErrorInfo(&error);
			osg::notify(osg::WARN) << error.ErrorString << std::endl;
			return false;
		}
	}

	return false;
}

unsigned int OculusDevice::screenResolutionWidth() const
{
	return  m_hmdDesc.Resolution.w;
}

unsigned int OculusDevice::screenResolutionHeight() const
{
	return  m_hmdDesc.Resolution.h;
}

osg::Matrix OculusDevice::projectionMatrixCenter() const
{
	osg::Matrix projectionMatrixCenter;
	projectionMatrixCenter = m_leftEyeProjectionMatrix.operator*(0.5) + m_rightEyeProjectionMatrix.operator*(0.5);
	return projectionMatrixCenter;
}

osg::Matrix OculusDevice::projectionMatrixLeft() const
{
	return m_leftEyeProjectionMatrix;
}

osg::Matrix OculusDevice::projectionMatrixRight() const
{
	return m_rightEyeProjectionMatrix;
}

osg::Matrix OculusDevice::projectionOffsetMatrixLeft() const
{
	osg::Matrix projectionOffsetMatrix;
	float offset = m_leftEyeProjectionMatrix(2, 0);
	projectionOffsetMatrix.makeTranslate(osg::Vec3(-offset, 0.0, 0.0));
	return projectionOffsetMatrix;
}

osg::Matrix OculusDevice::projectionOffsetMatrixRight() const
{
	osg::Matrix projectionOffsetMatrix;
	float offset = m_rightEyeProjectionMatrix(2, 0);
	projectionOffsetMatrix.makeTranslate(osg::Vec3(-offset, 0.0, 0.0));
	return projectionOffsetMatrix;
}

osg::Matrix OculusDevice::viewMatrixLeft() const
{
	osg::Matrix viewMatrix;
	viewMatrix.makeTranslate(-m_leftEyeAdjust);
	return viewMatrix;
}

osg::Matrix OculusDevice::viewMatrixRight() const
{
	osg::Matrix viewMatrix;
	viewMatrix.makeTranslate(-m_rightEyeAdjust);
	return viewMatrix;
}

void OculusDevice::resetSensorOrientation() const
{
	ovr_RecenterPose(m_session);
}

void OculusDevice::updatePose(unsigned int frameIndex)
{
	// Ask the API for the times when this frame is expected to be displayed.
	m_frameTiming = ovr_GetPredictedDisplayTime(m_session, frameIndex);

	m_viewOffset[0] = m_eyeRenderDesc[0].HmdToEyeViewOffset;
	m_viewOffset[1] = m_eyeRenderDesc[1].HmdToEyeViewOffset;

	// Query the HMD for the current tracking state.
	ovrTrackingState ts = ovr_GetTrackingState(m_session, m_frameTiming, ovrTrue);
	ovr_CalcEyePoses(ts.HeadPose.ThePose, m_viewOffset, m_eyeRenderPose);
	ovrPoseStatef headpose = ts.HeadPose;
	ovrPosef pose = headpose.ThePose;
	m_position.set(-pose.Position.x, -pose.Position.y, -pose.Position.z);
	m_position *= m_worldUnitsPerMetre;
	m_orientation.set(pose.Orientation.x, pose.Orientation.y, pose.Orientation.z, -pose.Orientation.w);
}

class OculusInitialDrawCallback : public osg::Camera::DrawCallback
{
public:
	virtual void operator()(osg::RenderInfo& renderInfo) const
	{
		osg::GraphicsOperation* graphicsOperation = renderInfo.getCurrentCamera()->getRenderer();
		osgViewer::Renderer* renderer = dynamic_cast<osgViewer::Renderer*>(graphicsOperation);
		if (renderer != nullptr)
		{
			// Disable normal OSG FBO camera setup because it will undo the MSAA FBO configuration.
			renderer->setCameraRequiresSetUp(false);
		}
	}
};

osg::Camera* OculusDevice::createRTTCamera(OculusDevice::Eye eye, osg::Transform::ReferenceFrame referenceFrame, const osg::Vec4& clearColor, osg::GraphicsContext* gc) const
{
	OculusTextureBuffer* buffer = m_textureBuffer[eye];

	osg::ref_ptr<osg::Camera> camera = new osg::Camera();
	camera->setClearColor(clearColor);
	camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
	camera->setRenderOrder(osg::Camera::PRE_RENDER, eye);
	camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
	camera->setAllowEventFocus(false);
	camera->setReferenceFrame(referenceFrame);
	camera->setViewport(0, 0, buffer->textureWidth(), buffer->textureHeight());
	camera->setGraphicsContext(gc);

	if (buffer->colorBuffer())
	{
		camera->attach(osg::Camera::COLOR_BUFFER, buffer->colorBuffer());
	}

	if (buffer->depthBuffer())
	{
		camera->attach(osg::Camera::DEPTH_BUFFER, buffer->depthBuffer());
	}

	if (m_samples != 0)
	{
		// If we are using MSAA, we don't want OSG doing anything regarding FBO
		// setup and selection because this is handled completely by 'setupMSAA'
		// and by pre and post render callbacks. So this initial draw callback is
		// used to disable normal OSG camera setup which would undo the MSAA buffer
		// configuration. Note that we have also implicity avoided the camera buffer
		// attachments above when MSAA is enabled because we don't want OSG to
		// affect the texture bindings handled by the pre and post render callbacks.
		camera->setInitialDrawCallback(new OculusInitialDrawCallback());
	}

	camera->setPreDrawCallback(new OculusPreDrawCallback(camera.get(), buffer));
	camera->setFinalDrawCallback(new OculusPostDrawCallback(camera.get(), buffer));

	return camera.release();
}

bool OculusDevice::submitFrame(unsigned int frameIndex)
{
	m_layerEyeFov.ColorTexture[0] = m_textureBuffer[0]->textureSet();
	m_layerEyeFov.ColorTexture[1] = m_textureBuffer[1]->textureSet();

	// Set render pose
	m_layerEyeFov.RenderPose[0] = m_eyeRenderPose[0];
	m_layerEyeFov.RenderPose[1] = m_eyeRenderPose[1];

	ovrLayerHeader* layers = &m_layerEyeFov.Header;
	ovrViewScaleDesc viewScale;
	viewScale.HmdToEyeViewOffset[0] = m_viewOffset[0];
	viewScale.HmdToEyeViewOffset[1] = m_viewOffset[1];
	viewScale.HmdSpaceToWorldScaleInMeters = m_worldUnitsPerMetre;
	ovrResult result = ovr_SubmitFrame(m_session, frameIndex, &viewScale, &layers, 1);
	return result == ovrSuccess;
}

void OculusDevice::blitMirrorTexture(osg::GraphicsContext* gc)
{
	m_mirrorTexture->blitTexture(gc);
}

void OculusDevice::setPerfHudMode(int mode)
{
	if (mode == 0) { ovr_SetInt(m_session, "PerfHudMode", (int)ovrPerfHud_Off); }

	if (mode == 1) { ovr_SetInt(m_session, "PerfHudMode", (int)ovrPerfHud_LatencyTiming); }

	if (mode == 2) { ovr_SetInt(m_session, "PerfHudMode", (int)ovrPerfHud_RenderTiming); }

	if (mode == 3) { ovr_SetInt(m_session, "PerfHudMode", (int)ovrPerfHud_PerfHeadroom); }

	if (mode == 4) { ovr_SetInt(m_session, "PerfHudMode", (int)ovrPerfHud_VersionInfo); }
}

void OculusDevice::setPositionalTrackingState(bool state)
{
	unsigned sensorCaps = 0;
	sensorCaps = ovrTrackingCap_Orientation | ovrTrackingCap_MagYawCorrection;

	if (state)
	{
		sensorCaps |= ovrTrackingCap_Position;
	}

	ovr_ConfigureTracking(m_session, sensorCaps, 0);
}

osg::GraphicsContext::Traits* OculusDevice::graphicsContextTraits() const
{
	// Create screen with match the Oculus Rift resolution
	osg::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();

	if (!wsi)
	{
		osg::notify(osg::NOTICE) << "Error, no WindowSystemInterface available, cannot create windows." << std::endl;
		return 0;
	}

	// Get the screen identifiers set in environment variable DISPLAY
	osg::GraphicsContext::ScreenIdentifier si;
	si.readDISPLAY();

	// If displayNum has not been set, reset it to 0.
	if (si.displayNum < 0)
	{
		si.displayNum = 0;
		osg::notify(osg::INFO) << "Couldn't get display number, setting to 0" << std::endl;
	}

	// If screenNum has not been set, reset it to 0.
	if (si.screenNum < 0)
	{
		si.screenNum = 0;
		osg::notify(osg::INFO) << "Couldn't get screen number, setting to 0" << std::endl;
	}

	unsigned int width, height;
	wsi->getScreenResolution(si, width, height);

	osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
	traits->hostName = si.hostName;
	traits->screenNum = si.screenNum;
	traits->displayNum = si.displayNum;
	traits->windowDecoration = true;
	traits->x = 50;
	traits->y = 50;
	traits->width = screenResolutionWidth() / 2;
	traits->height = screenResolutionHeight() / 2;
	traits->doubleBuffer = true;
	traits->sharedContext = nullptr;
	traits->vsync = false; // VSync should always be disabled for Oculus Rift applications, the SDK compositor handles the swap

	return traits.release();
}

/* Protected functions */
OculusDevice::~OculusDevice()
{
	// Delete mirror texture
	if (m_mirrorTexture.valid())
	{
		m_mirrorTexture->destroy();
	}

	// Delete texture and depth buffers
	for (int i = 0; i < 2; i++)
	{
		if (m_textureBuffer[i].valid())
		{
			m_textureBuffer[i]->destroy();
		}
	}

	ovr_Destroy(m_session);
	ovr_Shutdown();
}

void OculusDevice::printHMDDebugInfo()
{
	osg::notify(osg::ALWAYS) << "Product:         " << m_hmdDesc.ProductName << std::endl;
	osg::notify(osg::ALWAYS) << "Manufacturer:    " << m_hmdDesc.Manufacturer << std::endl;
	osg::notify(osg::ALWAYS) << "VendorId:        " << m_hmdDesc.VendorId << std::endl;
	osg::notify(osg::ALWAYS) << "ProductId:       " << m_hmdDesc.ProductId << std::endl;
	osg::notify(osg::ALWAYS) << "SerialNumber:    " << m_hmdDesc.SerialNumber << std::endl;
	osg::notify(osg::ALWAYS) << "FirmwareVersion: " << m_hmdDesc.FirmwareMajor << "." << m_hmdDesc.FirmwareMinor << std::endl;
}

void OculusDevice::initializeEyeRenderDesc()
{
	m_eyeRenderDesc[0] = ovr_GetRenderDesc(m_session, ovrEye_Left, m_hmdDesc.DefaultEyeFov[0]);
	m_eyeRenderDesc[1] = ovr_GetRenderDesc(m_session, ovrEye_Right, m_hmdDesc.DefaultEyeFov[1]);
}

void OculusDevice::calculateEyeAdjustment()
{
	ovrVector3f leftEyeAdjust = m_eyeRenderDesc[0].HmdToEyeViewOffset;
	ovrVector3f rightEyeAdjust = m_eyeRenderDesc[1].HmdToEyeViewOffset;

	m_leftEyeAdjust.set(leftEyeAdjust.x, leftEyeAdjust.y, leftEyeAdjust.z);
	m_rightEyeAdjust.set(rightEyeAdjust.x, rightEyeAdjust.y, rightEyeAdjust.z);

	// Display IPD
	float ipd = (m_leftEyeAdjust - m_rightEyeAdjust).length();
	osg::notify(osg::ALWAYS) << "Interpupillary Distance (IPD): " << ipd * 1000.0f << " mm" << std::endl;

	// Scale to world units
	m_leftEyeAdjust *= m_worldUnitsPerMetre;
	m_rightEyeAdjust *= m_worldUnitsPerMetre;
}

void OculusDevice::calculateProjectionMatrices()
{
	unsigned int projectionModifier = ovrProjection_RightHanded;
	projectionModifier |= ovrProjection_ClipRangeOpenGL;

	ovrMatrix4f leftEyeProjectionMatrix = ovrMatrix4f_Projection(m_eyeRenderDesc[0].Fov, m_nearClip, m_farClip, projectionModifier);
	// Transpose matrix
	m_leftEyeProjectionMatrix.set(leftEyeProjectionMatrix.M[0][0], leftEyeProjectionMatrix.M[1][0], leftEyeProjectionMatrix.M[2][0], leftEyeProjectionMatrix.M[3][0],
								  leftEyeProjectionMatrix.M[0][1], leftEyeProjectionMatrix.M[1][1], leftEyeProjectionMatrix.M[2][1], leftEyeProjectionMatrix.M[3][1],
								  leftEyeProjectionMatrix.M[0][2], leftEyeProjectionMatrix.M[1][2], leftEyeProjectionMatrix.M[2][2], leftEyeProjectionMatrix.M[3][2],
								  leftEyeProjectionMatrix.M[0][3], leftEyeProjectionMatrix.M[1][3], leftEyeProjectionMatrix.M[2][3], leftEyeProjectionMatrix.M[3][3]);

	ovrMatrix4f rightEyeProjectionMatrix = ovrMatrix4f_Projection(m_eyeRenderDesc[1].Fov, m_nearClip, m_farClip, projectionModifier);
	// Transpose matrix
	m_rightEyeProjectionMatrix.set(rightEyeProjectionMatrix.M[0][0], rightEyeProjectionMatrix.M[1][0], rightEyeProjectionMatrix.M[2][0], rightEyeProjectionMatrix.M[3][0],
								   rightEyeProjectionMatrix.M[0][1], rightEyeProjectionMatrix.M[1][1], rightEyeProjectionMatrix.M[2][1], rightEyeProjectionMatrix.M[3][1],
								   rightEyeProjectionMatrix.M[0][2], rightEyeProjectionMatrix.M[1][2], rightEyeProjectionMatrix.M[2][2], rightEyeProjectionMatrix.M[3][2],
								   rightEyeProjectionMatrix.M[0][3], rightEyeProjectionMatrix.M[1][3], rightEyeProjectionMatrix.M[2][3], rightEyeProjectionMatrix.M[3][3]);
}

void OculusDevice::setupLayers()
{
	m_layerEyeFov.Header.Type = ovrLayerType_EyeFov;
	m_layerEyeFov.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft;   // Because OpenGL.

	ovrRecti viewPort[2];
	viewPort[0].Pos.x = 0;
	viewPort[0].Pos.y = 0;
	viewPort[0].Size.w = m_textureBuffer[0]->textureWidth();
	viewPort[0].Size.h = m_textureBuffer[0]->textureHeight();

	viewPort[1].Pos.x = 0;
	viewPort[1].Pos.y = 0;
	viewPort[1].Size.w = m_textureBuffer[1]->textureWidth();
	viewPort[1].Size.h = m_textureBuffer[1]->textureHeight();

	m_layerEyeFov.Viewport[0] = viewPort[0];
	m_layerEyeFov.Viewport[1] = viewPort[1];
	m_layerEyeFov.Fov[0] = m_eyeRenderDesc[0].Fov;
	m_layerEyeFov.Fov[1] = m_eyeRenderDesc[1].Fov;
}

void OculusDevice::trySetProcessAsHighPriority() const
{
	// Require at least 4 processors, otherwise the process could occupy the machine.
	if (OpenThreads::GetNumberOfProcessors() >= 4)
	{
#ifdef _WIN32
		SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
#endif
	}
}

void OculusRealizeOperation::operator() (osg::GraphicsContext* gc)
{
	if (!m_realized)
	{
		OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex);
		gc->makeCurrent();

		if (osgViewer::GraphicsWindow* window = dynamic_cast<osgViewer::GraphicsWindow*>(gc))
		{
			// Run wglSwapIntervalEXT(0) to force VSync Off
			window->setSyncToVBlank(false);
		}

		osg::ref_ptr<osg::State> state = gc->getState();
		m_device->createRenderBuffers(state);
		// Init the oculus system
		m_device->init();
	}

	m_realized = true;
}

void OculusSwapCallback::swapBuffersImplementation(osg::GraphicsContext* gc)
{
	// Submit rendered frame to compositor
	m_device->submitFrame();

	// Blit mirror texture to backbuffer
	m_device->blitMirrorTexture(gc);

	// Run the default system swapBufferImplementation
	gc->swapBuffersImplementation();
}


text:
<?php

namespace yii\mutex;

use Yii;
use yii\base\InvalidConfigException;
use yii\helpers\FileHelper;

/**
 * FileMutex implements mutex "lock" mechanism via local file system files.
 * This component relies on PHP `flock()` function.
 *
 * Application configuration example:
 *
 * ```
 * [
 *     'components' => [
 *         'mutex' => [
 *             'class' => 'yii\mutex\FileMutex'
 *         ],
 *     ],
 * ]
 * ```
 *
 * Note: this component can maintain the locks only for the single web server,
 * it probably will not suffice to your in case you are using cloud server solution.
 *
 * Warning: due to `flock()` function nature this component is unreliable when
 * using a multithreaded server API like ISAPI.
 *
 * @see Mutex
 *
 * @author resurtm <resurtm@gmail.com>
 * @since 2.0
 */
class FileMutex extends Mutex
{
    /**
     * @var string the directory to store mutex files. You may use path alias here.
     * Defaults to the "mutex" subdirectory under the application runtime path.
     */
    public $mutexPath = '@runtime/mutex';
    /**
     * @var int the permission to be set for newly created mutex files.
     * This value will be used by PHP chmod() function. No umask will be applied.
     * If not set, the permission will be determined by the current environment.
     */
    public $fileMode;
    /**
     * @var int the permission to be set for newly created directories.
     * This value will be used by PHP chmod() function. No umask will be applied.
     * Defaults to 0775, meaning the directory is read-writable by owner and group,
     * but read-only for other users.
     */
    public $dirMode = 0775;

    /**
     * @var resource[] stores all opened lock files. Keys are lock names and values are file handles.
     */
    private $_files = [];

    /**
     * Initializes mutex component implementation dedicated for UNIX, GNU/Linux, Mac OS X, and other UNIX-like
     * operating systems.
     * @throws InvalidConfigException
     */
    public function init()
    {
        $this->mutexPath = Yii::getAlias($this->mutexPath);
        if (!is_dir($this->mutexPath)) {
            FileHelper::createDirectory($this->mutexPath, $this->dirMode, true);
        }
    }

    /**
     * Acquires lock by given name.
     * @param string $name of the lock to be acquired.
     * @param int $timeout to wait for lock to become released.
     * @return bool acquiring result.
     */
    protected function acquireLock($name, $timeout = 0)
    {
        $file = fopen($this->getLockFilePath($name), 'w+');
        if ($file === false) {
            return false;
        }
        if ($this->fileMode !== null) {
            @chmod($this->getLockFilePath($name), $this->fileMode);
        }
        $waitTime = 0;
        while (!flock($file, LOCK_EX | LOCK_NB)) {
            $waitTime++;
            if ($waitTime > $timeout) {
                fclose($file);

                return false;
            }
            sleep(1);
        }
        $this->_files[$name] = $file;

        return true;
    }

    /**
     * Releases lock by given name.
     * @param string $name of the lock to be released.
     * @return bool release result.
     */
    protected function releaseLock($name)
    {
        if (!isset($this->_files[$name]) || !flock($this->_files[$name], LOCK_UN)) {
            return false;
        } else {
            fclose($this->_files[$name]);
            unlink($this->getLockFilePath($name));
            unset($this->_files[$name]);

            return true;
        }
    }

    /**
     * Generate path for lock file.
     * @param string $name
     * @return string
     * @since 2.0.10
     */
    protected function getLockFilePath($name)
    {
        return $this->mutexPath . DIRECTORY_SEPARATOR . md5($name) . '.lock';
    }
}

redpajama_set_name: RedPajamaGithub


text:
import { Controller, Get } from '@nestjs/common';
import { PhotoService } from './photo.service';
import { Photo } from './photo.entity';

@Controller('photo')
export class PhotoController {
  constructor(private readonly photoService: PhotoService) {}

  @Get()
  findAll(): Promise<Photo[]> {
    return this.photoService.findAll();
  }
}


text:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Tentang extends CI_Controller {

	public function index()
	{
		$this->load->view('templates/header.php');
		$this->load->view('templates/nav.php');
		$this->load->view('tentang');
		$this->load->view('templates/footer.php');
	}
}


text:
.. _minio-external-identity-management-openid:

===================================
OpenID External Identity Management
===================================

.. default-domain:: minio

.. contents:: Table of Contents
   :local:
   :depth: 2

Overview
--------

MinIO supports using an OpenID Connect (OIDC) compatible IDentity Provider (IDP)
such as Okta, KeyCloak, Dex, Google, or Facebook for external management of user
identities. Configuring an external :abbr:`IDP (IDentity Provider)` enables
Single-Sign On workflows, where applications authenticate against the external
:abbr:`IDP (IDentity Provider)` before accessing MinIO.

MinIO by default denies access to all actions or resources not explicitly
allowed by a user's assigned or inherited :ref:`policies <minio-policy>`. Users
managed by an OIDC provider must specify the necessary policies as part of the
user profile data. See :ref:`Access Control for OIDC Managed Identities
<minio-external-identity-management-openid-access-control>` for more
information.

See :ref:`minio-authenticate-using-openid-generic` for instructions on enabling
external identity management using an :abbr:`OIDC (OpenID Connect)` compatible
service.

.. admonition:: MinIO Supports At Most One Configured IDentity Provider
   :class: important

   Configuring an external IDP disables the :ref:`MinIO internal IDP
   <minio-internal-idp>` and prevents the configuration of any other
   external IDP.

   The external :abbr:`IDP (IDentity Provider)` must have *at least* one
   configured user identity with the required :ref:`policy claims
   <minio-external-identity-management-openid-access-control>`. If no such user
   exists, the MinIO server is effectively inaccessible outside of using the
   :ref:`root <minio-users-root>` user.

Authentication and Authorization Flow
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The login flow for an application using :abbr:`OIDC (OpenID Connect)`
credentials is as follows:

1. Authenticate to the configured :abbr:`OIDC (OpenID Connect)`
   provider and retrieve a
   `JSON Web Token (JWT) <https://jwt.io/introduction>`__.

   MinIO only supports the
   `OpenID Authorization Code Flow
   <https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth>`__.
   Authentication using Implicit Flow is not supported.

2. Specify the :abbr:`JWT (JSON Web Token)` to the MinIO Security Token Service
   (STS) :ref:`minio-sts-assumerolewithwebidentity` API endpoint.

   MinIO verifies the :abbr:`JWT (JSON Web Token)` against the
   configured OIDC provider.

   If the JWT is valid, MinIO checks for a :ref:`claim
   <minio-external-identity-management-openid-access-control>` specifying a list
   of one or more :ref:`policies <minio-policy>` to assign to the
   authenticated user. MinIO defaults to checking the ``policy`` claim.

3. MinIO returns temporary credentials in the STS API response in the form of an
   access key, secret key, and session token. The credentials have
   permissions matching those policies specified in the JWT claim.

4. Applications use the temporary credentials returned by the STS endpoint to
   perform authenticated S3 operations on MinIO.

MinIO provides an example Go application
:minio-git:`web-identity.go <minio/blob/master/docs/sts/web-identity.go>` that
handles the full login flow.

OIDC users can alternatively create :ref:`service accounts <minio-idp-service-account>` associated to their AD/LDAP user. Service accounts are long-lived credentials which inherit their privileges from the parent user. The parent user can further restrict those privileges while creating the service account. To create a new service account, log into the :ref:`MinIO Console <minio-console>` using the OIDC-managed user credentials. From the :guilabel:`Identity` section of the left navigation, select :guilabel:`Service Accounts` followed by the :guilabel:`Create service account +` button.

.. _minio-external-identity-management-openid-access-control:

Access Control for Externally Managed Identities
------------------------------------------------

MinIO uses :ref:`Policy Based Access Control (PBAC) <minio-access-management>`
to define the actions and resources to which an authenticated user has access.
MinIO supports creating and managing :ref:`policies <minio-policy>` which an
externally managed user can claim.

For identities managed by the external OpenID Connect (OIDC) compatible
provider, MinIO uses a `JSON Web Token claim
<https://datatracker.ietf.org/doc/html/rfc7519#section-4>`__ to identify the
:ref:`policy <minio-policy>` to assign to the authenticated user.

MinIO by default looks for a ``policy`` claim and reads a list of one or more
policies to assign. MinIO attempts to match existing policies to those
specified in the JWT claim. If none of the specified policies exist on the MinIO
deployment, MinIO denies authorization for any and all operations issued
by that user. For example, consider a claim with the following key-value
assignment:

.. code-block:: shell

   policy="readwrite_data,read_analytics,read_logs"

The specified policy claim directs MinIO to attach the policies with names
matching ``readwrite_data``, ``read_analytics``, and ``read_logs`` to the
authenticated user.

You can set a custom policy claim using the
:envvar:`MINIO_IDENTITY_OPENID_CLAIM_NAME` environment variable
*or* by using :mc-cmd:`mc admin config set` to set the
:mc-conf:`identity_openid claim_name <identity_openid.claim_name>` setting.

You can use a `JWT Debugging tool <https://jwt.io/>`__ to decode the returned
JWT token and validate that the user attributes include the required claims. See
`RFC 7519: JWT Claim
<https://datatracker.ietf.org/doc/html/rfc7519#section-4>`__ for more
information on JWT claims. Defer to the documentation for your preferred OIDC
provider for instructions on configuring user claims.

MinIO provides :ref:`built-in policies <minio-policy-built-in>` for basic access
control. You can create new policies using the :mc:`mc admin policy` command, or
by using the MinIO Console. MinIO does not support assigning :ref:`groups
<minio-groups>` to an :abbr:`OIDC (OpenID Connect)` managed identity. Specify
any and all policies to attach to the user as part of its :abbr:`JWT (JWT)`
policy claim.

.. toctree::
   :titlesonly:
   :hidden:

   /security/openid-external-identity-management/configure-openid-external-identity-management
   /security/openid-external-identity-management/AssumeRoleWithWebIdentity


text:
<?php

namespace spec\Samurai\Onikiri\Driver;

use Samurai\Onikiri\Database;
use Samurai\Samurai\Component\Spec\Context\PHPSpecContext;

class PgsqlDriverSpec extends PHPSpecContext
{
    public $application;

    public function it_is_initializable()
    {
        $this->shouldHaveType('Samurai\Onikiri\Driver\PgsqlDriver');
    }

    public function it_connects_to_pgsql(Database $d)
    {
        if (! $this->application->config('spec.pgsql.database.defined'))
            $this->skipExample('Set env "ONIKIRI_SPEC_PGSQL_(USER|PASS|HOST|PORT|DATABASE)"');
        if (defined('HHVM_VERSION'))
            $this->skipExample('HHVM is pgsql not supported.');

        $d->getUser()->willReturn($this->application->config('spec.pgsql.database.user'));
        $d->getPassword()->willReturn($this->application->config('spec.pgsql.database.pass'));
        $d->getHostName()->willReturn($this->application->config('spec.pgsql.database.host'));
        $d->getPort()->willReturn($this->application->config('spec.pgsql.database.port'));
        $d->getDatabaseName()->willReturn($this->application->config('spec.pgsql.database.name'));
        $d->getOptions()->willReturn([]);

        $connection = $this->connect($d);
        $connection->shouldHaveType('Samurai\Onikiri\Connection');
    }
}


text:
package org.metacsp.multi.temporalRectangleAlgebra;

import org.metacsp.framework.ConstraintSolver;
import org.metacsp.framework.multi.MultiConstraintSolver;
import org.metacsp.multi.activity.ActivityNetworkSolver;
import org.metacsp.multi.allenInterval.AllenIntervalConstraint;
import org.metacsp.multi.spatial.blockAlgebra.BlockAlgebraConstraint;
import org.metacsp.multi.spatial.blockAlgebra.BlockConstraintSolver;
import org.metacsp.multi.spatial.blockAlgebra.UnaryBlockConstraint;
import org.metacsp.multi.symbols.SymbolicValueConstraint;

public class SpatialFluentSolver2 extends MultiConstraintSolver{

	/**
	 *
	 */
	private static final long serialVersionUID = 1449731304165896873L;
	protected int IDs = 0;

	public SpatialFluentSolver2(long origin, long horizon) {
		super(new Class[] {BlockAlgebraConstraint.class, UnaryBlockConstraint.class, AllenIntervalConstraint.class, SymbolicValueConstraint.class},
				SpatialFluent2.class,
				createConstraintSolvers(origin, horizon, -1),
				new int[] {1,1});
	}

	public SpatialFluentSolver2(long origin, long horizon, int maxFluent) {
		super(new Class[] {BlockAlgebraConstraint.class, UnaryBlockConstraint.class, AllenIntervalConstraint.class, SymbolicValueConstraint.class},
				SpatialFluent2.class,
				createConstraintSolvers(origin, horizon, maxFluent),
				new int[] {1,1});
	}

	private static ConstraintSolver[] createConstraintSolvers(long origin, long horizon, int maxFluents) {
		ConstraintSolver[] ret = maxFluents != -1 ? new ConstraintSolver[] {new BlockConstraintSolver(origin, horizon, maxFluents),
				new ActivityNetworkSolver(origin, horizon, maxFluents)}
			:new ConstraintSolver[] {new BlockConstraintSolver(origin, horizon), new ActivityNetworkSolver(origin, horizon)};
		return ret;
	}

	@Override
	public boolean propagate() {
		return false;
	}

}


text:
<resources>

    <!-- Strings related to login -->
    <string name="prompt_username">Username</string>
    <string name="prompt_password">Password</string>
    <string name="action_sign_in">Sign In</string>

    <string name="error_invalid_email">This username is invalid</string>
    <string name="error_incorrect_password">This password is incorrect</string>
    <string name="error_field_required">This field is required</string>
</resources>


text:
<?php

namespace RemoteServerBundle\Server;

/**
 * Class BaseFtp
 * @package RemoteServerBundle\Server
 */
Abstract class BaseFtp implements FileServerInterface, ServerInterface
{
    /**
     * FTP Resource
     */
    private $ftp;

    /**
     * @var string
     */
    private $ftp_host;

    /**
     * @var integer
     */
    private $ftp_port;

    /**
     * @var string
     */
    private $ftp_user;

    /**
     * @var string
     */
    private $ftp_password;

    /**
     * @var string
     */
    private $ftp_dir;

    /**
     * @param array $configuration
     */
    public function __construct(array $configuration)
    {
        $this
        ->setFtpHost($configuration['host'])
        ->setFtpPort($configuration['port'])
        ->setFtpUser($configuration['username'])
        ->setFtpPassword($configuration['password'])
        ->setFtpDir($configuration['path']);
    }

    /**
     * Reset the connection
     * @return bool
     */
    public function reset()
    {
        unset($this->ftp);
        $this->ftp = null;

        return true;
    }

    /**
     * @return string
     */
    public function getFtpHost()
    {
        return $this->ftp_host;
    }

    /**
     * @param $host
     * @return $this
     */
    public function setFtpHost($host)
    {
        $this->ftp_host = $host;

        return $this;
    }

    /**
     * @return int
     */
    public function getFtpPort()
    {
        return $this->ftp_port;
    }

    /**
     * @param $ftp_port
     * @return $this
     */
    public function setFtpPort($ftp_port)
    {
        $this->ftp_port = $ftp_port;

        return $this;
    }

    /**
     * @return string
     */
    public function getFtpUser()
    {
        return $this->ftp_user;
    }

    /**
     * @param $ftpUser
     * @return $this
     */
    public function setFtpUser($ftpUser)
    {
        $this->ftp_user = $ftpUser;

        return $this;
    }

    /**
     * @return string
     */
    public function getFtpPassword()
    {
        return $this->ftp_password;
    }

    /**
     * @param $ftpPassword
     * @return $this
     */
    public function setFtpPassword($ftpPassword)
    {
        $this->ftp_password = $ftpPassword;

        return $this;
    }

    /**
     * @return string
     */
    public function getFtpDir()
    {
        return $this->ftp_dir;
    }

    /**
     * @param $ftpDir
     * @return $this
     */
    public function setFtpDir($ftpDir)
    {
        $this->ftp_dir = $ftpDir;

        return $this;
    }

    public function getFtp()
    {
        if(is_null($this->ftp)) {
            $this->connect();
        }

        return $this->ftp;
    }

    /**
     * @param $ftpRessource
     * @return $this
     */
    public function setFtp($ftpRessource)
    {
        $this->ftp = $ftpRessource;

        return $this;
    }

    /**
     * @inheritdoc
     */
    public function delete($pathToFile)
    {
        throw new \Exception(sprintf("Function '%s' not implemented in %s class", 'delete()', get_class($this)));
    }

    /**
     * @inheritdoc
     */
    public function getFilesInFolder($path)
    {
        throw new \Exception(sprintf("Function '%s' not implemented in %s class", 'getFilesInFolder()', get_class($this)));
    }

    /**
     * @inheritdoc
     */
    public function createDirectory($directoryName, $path = "/")
    {
        throw new \Exception(sprintf("Function '%s' not implemented in %s class", 'createDirectory()', get_class($this)));
    }

    /**
     * @inheritdoc
     */
    public function getFileModificationTime($filepath)
    {
        throw new \Exception(sprintf("Function '%s' not implemented in %s class", 'getFileModificationTime()', get_class($this)));
    }

    /**
     * @inheritdoc
     */
    public function getFileSize($filepath)
    {
        throw new \Exception(sprintf("Function '%s' not implemented in %s class", 'getFileModificationTime()', get_class($this)));
    }
}


text:
const express=require('express');
const webpack=require('webpack');
const fs=require('fs');
const path=require('path');
const webpackDevMiddleware=require('webpack-dev-middleware');
const webpackHotMiddleware=require('webpack-hot-middleware');
const webpackConfig=require('./webpack.config.js');

const app=express();
const isProd=process.env.NODE_ENV === 'production';
const port=3000;

if (isProd) {
	app.use(express.static(path.join(__dirname, '/src/index.html')));
	app.get('*', function(req, res) {
		res.sendFile(path.join(__dirname, '/src/index.html'));
	});
} else {
	const compiler=webpack(webpackConfig);
	app.use(webpackDevMiddleware(compiler, {
		noInfo: true,
		publicPath: webpackConfig.output.publicPath
	}));
	app.use(webpackHotMiddleware(compiler));

	app.get('*', function(req, res) {
		res.write(fs.readFileSync(path.join(__dirname, '/src/index.html')));
		res.end();
	});
}

app.listen(port, function(err) {
	if (err) {
		console.log(err);
	}
	console.info(`Listening on port ${port}`);
});


text:
package com.hazelcast.internal.cluster;

import com.hazelcast.cluster.Cluster;
import com.hazelcast.instance.impl.NodeExtension;
import com.hazelcast.spi.properties.ClusterProperty;
import com.hazelcast.version.Version;

/**
 * Listeners interested in acting upon cluster version update should implement this interface.
 * Services registered with the Hazelcast {@link com.hazelcast.spi.impl.servicemanager.ServiceManager} which implement this
 * interface do not have have to register themselves, as their {@link #onClusterVersionChange(Version)} method will be
 * invoked automatically.
 *
 * Other listeners have to register themselves with {@link NodeExtension#registerListener(Object)}.
 * Upon registration, the listener's {@link #onClusterVersionChange(Version)} method will be invoked once with the current
 * value of the cluster version.
 *
 * @see Cluster#getClusterVersion()
 * @see ClusterService#changeClusterVersion(Version)
 * @since 3.8
 */
public interface ClusterVersionListener {

    /**
     * Invoked on registered listeners after the new cluster version has been applied. Listeners are executed synchronously
     * immediately after {@code ClusterStateManager#version} has been updated and while the cluster service lock
     * {@code ClusterServiceImpl#lock} is still locked, as part of the commit phase of the transaction changing
     * the cluster version. Unhandled exceptions from listeners implementation will break the new version commit and a slow
     * implementation will stall the system and may cause a transaction timeout.
     * If new cluster version is {@code null} and property
     * {@link ClusterProperty#INIT_CLUSTER_VERSION} is set, the version set by this property
     * will be provided as argument to the listener. If neither are set, running node's codebase version will be used.
     *
     * @param newVersion the new version
     */
    void onClusterVersionChange(Version newVersion);

}


text:
package com.cavallorama.services;

import com.cavallorama.model.Customer;
import com.cavallorama.model.Item;
import com.cavallorama.model.LineItem;
import com.cavallorama.model.Order;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;

import java.util.ArrayList;
import java.util.UUID;

/**
 * Created with IntelliJ IDEA.
 * User: francescocavallo
 * Date: 21/03/13
 * Time: 00.02
 * To change this template use File | Settings | File Templates.
 */
public class InitMongoDBService {

    @Autowired
    private MongoTemplate mongoTemplate;

    public void init() {

        //reset on startup
        mongoTemplate.dropCollection("customers");
        mongoTemplate.dropCollection("items");
        mongoTemplate.dropCollection("line_items");
        mongoTemplate.dropCollection("orders");

         // five customers here
        Customer c1 = new Customer();
        c1.setId(UUID.randomUUID().toString());
        c1.setCustomerCode("C0001");
        c1.setDescription("fake description");
        c1.setName("Telco Business Inc.");

        Customer c2 = new Customer();
        c2.setId(UUID.randomUUID().toString());
        c2.setCustomerCode("C0002");
        c2.setDescription("fake description");
        c2.setName("Admin Business Co.");

        Customer c3 = new Customer();
        c3.setId(UUID.randomUUID().toString());
        c3.setCustomerCode("C0003");
        c3.setDescription("fake description");
        c3.setName("Bakery International");

        Customer c4 = new Customer();
        c4.setId(UUID.randomUUID().toString());
        c4.setCustomerCode("C0004");
        c4.setDescription("fake description");
        c4.setName("Airfly Cute");

        Customer c5 = new Customer();
        c5.setId(UUID.randomUUID().toString());
        c5.setCustomerCode("C0005");
        c5.setDescription("fake description");
        c5.setName("Yet Another, Dude Inc.");

        //six items here
        Item i1 = new Item();
        i1.setId(UUID.randomUUID().toString());
        i1.setCode("I000001");
        i1.setDescription("Bolts");

        Item i2 = new Item();
        i2.setId(UUID.randomUUID().toString());
        i2.setCode("I000002");
        i2.setDescription("Heels");

        Item i3 = new Item();
        i3.setId(UUID.randomUUID().toString());
        i3.setCode("I000003");
        i3.setDescription("masks");

        Item i4 = new Item();
        i4.setId(UUID.randomUUID().toString());
        i4.setCode("I000004");
        i4.setDescription("Iron Forges");

        Item i5 = new Item();
        i5.setId(UUID.randomUUID().toString());
        i5.setCode("I000005");
        i5.setDescription("Chargebacks");

        Item i6 = new Item();
        i6.setId(UUID.randomUUID().toString());
        i6.setCode("I000006");
        i6.setDescription("Six-packs");

        //lineItems here

        LineItem li1 = new LineItem();
        li1.setId(UUID.randomUUID().toString());
        li1.setItem(i1);
        li1.setQty(25000);
        LineItem li2 = new LineItem();
        li2.setId(UUID.randomUUID().toString());
        li2.setItem(i4);
        li2.setQty(23);
        LineItem li3 = new LineItem();
        li3.setId(UUID.randomUUID().toString());
        li3.setItem(i5);
        li3.setQty(111);
        LineItem li4 = new LineItem();
        li4.setId(UUID.randomUUID().toString());
        li4.setItem(i5);
        li4.setQty(150);
        LineItem li5 = new LineItem();
        li5.setId(UUID.randomUUID().toString());
        li5.setItem(i2);
        li5.setQty(3000);
        LineItem li6 = new LineItem();
        li6.setId(UUID.randomUUID().toString());
        li6.setItem(i2);
        li6.setQty(34);
        LineItem li7 = new LineItem();
        li7.setId(UUID.randomUUID().toString());
        li7.setItem(i4);
        li7.setQty(1200);
        LineItem li8 = new LineItem();
        li8.setId(UUID.randomUUID().toString());
        li8.setItem(i6);
        li8.setQty(343);
        LineItem li9 = new LineItem();
        li9.setId(UUID.randomUUID().toString());
        li9.setItem(i6);
        li9.setQty(100);
        LineItem li10 = new LineItem();
        li10.setId(UUID.randomUUID().toString());
        li10.setItem(i1);
        li10.setQty(450);
        LineItem li11 = new LineItem();
        li11.setId(UUID.randomUUID().toString());
        li11.setItem(i2);
        li11.setQty(76);

        //a few orders
        ArrayList<LineItem> a;
        Order o1 = new Order();
        o1.setId(UUID.randomUUID().toString());
        o1.setCustomer(c1);
        a = new ArrayList<>();
        a.add(li1);
        a.add(li10);
        a.add(li4);
        o1.setLineItems(a);

        Order o2 = new Order();
        o2.setId(UUID.randomUUID().toString());
        o2.setCustomer(c1);
        a = new ArrayList<>();
        a.add(li3);
        a.add(li6);
        a.add(li11);
        o2.setLineItems(a);

        Order o3 = new Order();
        o3.setId(UUID.randomUUID().toString());
        o3.setCustomer(c1);
        a = new ArrayList<>();
        a.add(li2);
        a.add(li3);
        a.add(li7);
        o3.setLineItems(a);

        Order o4 = new Order();
        o4.setId(UUID.randomUUID().toString());
        o4.setCustomer(c5);
        a = new ArrayList<>();
        a.add(li8);
        o4.setLineItems(a);

        Order o5 = new Order();
        o5.setId(UUID.randomUUID().toString());
        o5.setCustomer(c1);
        a = new ArrayList<>();
        a.add(li9);
        o5.setLineItems(a);

        Order o6 = new Order();
        o6.setId(UUID.randomUUID().toString());
        o6.setCustomer(c1);
        a = new ArrayList<>();
        a.add(li1);
        a.add(li10);
        a.add(li4);
        a.add(li2);
        a.add(li3);
        o6.setLineItems(a);

        mongoTemplate.insert(c1,"customers");
        mongoTemplate.insert(c2,"customers");
        mongoTemplate.insert(c3,"customers");
        mongoTemplate.insert(c4,"customers");
        mongoTemplate.insert(c5,"customers");
        mongoTemplate.insert(i1,"items");
        mongoTemplate.insert(i2,"items");
        mongoTemplate.insert(i3,"items");
        mongoTemplate.insert(i4,"items");
        mongoTemplate.insert(i5,"items");
        mongoTemplate.insert(i6,"items");
        mongoTemplate.insert(li1,"line_items");
        mongoTemplate.insert(li2,"line_items");
        mongoTemplate.insert(li3,"line_items");
        mongoTemplate.insert(li4,"line_items");
        mongoTemplate.insert(li5,"line_items");
        mongoTemplate.insert(li6,"line_items");
        mongoTemplate.insert(li7,"line_items");
        mongoTemplate.insert(li8,"line_items");
        mongoTemplate.insert(li9,"line_items");
        mongoTemplate.insert(li10,"line_items");
        mongoTemplate.insert(li11,"line_items");
        mongoTemplate.insert(o1,"orders");
        mongoTemplate.insert(o2,"orders");
        mongoTemplate.insert(o3,"orders");
        mongoTemplate.insert(o4,"orders");
        mongoTemplate.insert(o5,"orders");
        mongoTemplate.insert(o6,"orders");

    }
}


text:
<?php

namespace AntiMattr\Bundle\ContentMongoDBBundle\Twig\Extension;

use Doctrine\Common\Collections\Collection;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Twig_Function_Method as TFM;

class ContentMongoDBExtension extends \Twig_Extension
{
    private $container;

    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    public function getName()
    {
        return 'content_mongodb';
    }

    public function getFunctions()
    {
        return [
            'content_nav' => new TFM($this, 'getNav'),
            'content_sort' => new TFM($this, 'sortByPosition'),
        ];
    }

    /**
     * @param string $slug
     *
     * @return AntiMattr\Bundle\ContentMongoDBBundle\Document\Nav
     */
    public function getNav($slug)
    {
        return $this->getContentManager()->read('AntiMattrContentMongoDBBundle:Nav', $slug);
    }

    /**
     * @param Collection[AbstractContent] $collection
     *
     * @return ArrayIterator
     */
    public function sortByPosition(Collection $collection)
    {
        $iterator = $collection->getIterator();

        $iterator->uasort(function ($first, $second) {
            return (int) $first->getPosition() > (int) $second->getPosition() ? 1 : -1;
        });

        return $iterator;
    }

    /**
     * @return AntiMattr\Bundle\ContentMongoDBBundle\Service\ContentMongoDBManager
     */
    protected function getContentManager()
    {
        return $this->container->get('antimattr.content_mongodb_manager');
    }
}


text:
<?php

namespace cryptopupua\KunaApi\Model;

/**
 * Class MyAccount
 * @package cryptopupua\KunaApi\Model
 */
class MyAccount
{
    /**
     * @var string
     */
    protected $currency;

    /**
     * Account balance
     * @var float
     */
    private $balance;

    /**
     * Locked amount
     * @var float
     */
    private $locked;

    /**
     * @return string
     */
    public function getCurrency(): string
    {
        return $this->currency;
    }

    /**
     * @param string $currency
     */
    public function setCurrency(string $currency): void
    {
        $this->currency = $currency;
    }

    /**
     * @return float
     */
    public function getBalance(): float
    {
        return $this->balance;
    }

    /**
     * @param float $balance
     */
    public function setBalance(float $balance): void
    {
        $this->balance = $balance;
    }

    /**
     * @return float
     */
    public function getLocked(): float
    {
        return $this->locked;
    }

    /**
     * @param float $locked
     */
    public function setLocked(float $locked): void
    {
        $this->locked = $locked;
    }
}


text:
namespace XSockets
{
    using System;
    using System.Threading;
    using Common.Interfaces;

    public partial class Controller : IController
    {
        private int _qosId;
        public int GetIdForQoS()
        {
            if (_qosId >= UInt16.MaxValue)
                _qosId = UInt16.MinValue;
            Interlocked.Increment(ref _qosId);
            return _qosId;
        }
    }
}


text:
import { Injectable } from '@angular/core';
import { CanActivate } from '@angular/router';
import { Location } from '@angular/common';

@Injectable()
export class AuthenticationCallbackActivateGuard implements CanActivate {
  // attempt to fix issues with auth0-lock in redirect mode and angular2 router using hashlocationstrategy
  // from here: http://stackoverflow.com/a/39701248

  constructor(private location: Location) { }

  canActivate() {
    // You may want to make a more robust check here
    console.log('can activate:', this.location.path(true).indexOf("access_token") === -1)
    return this.location.path(true).indexOf("access_token") === -1;
  }
}


text:
namespace OMLT
{
	template<>
	TrainingSchedule<ContrastiveDivergence>* TrainingSchedule<ContrastiveDivergence>::FromJSON(const std::string& json)
	{
		TrainingSchedule<ContrastiveDivergence>* result = nullptr;

		cJSON* root = cJSON_Parse(json.c_str());
		if(root)
		{
			cJSON* cj_type = cJSON_GetObjectItem(root, "Type");

			if(!cj_type || (strcmp(cj_type->valuestring, "RBM") != 0 && strcmp(cj_type->valuestring, "RestrictedBoltzmannMachine") != 0))
			{
				goto Error;
			}

			cJSON* cj_visible_type = cJSON_GetObjectItem(root, "VisibleType");
			cJSON* cj_visible_count = cJSON_GetObjectItem(root, "VisibleCount");
			cJSON* cj_hidden_type = cJSON_GetObjectItem(root, "HiddenType");
			cJSON* cj_hidden_count = cJSON_GetObjectItem(root, "HiddenCount");
			cJSON* cj_minibatch_size = cJSON_GetObjectItem(root, "MinibatchSize");
			cJSON* cj_seed = cJSON_GetObjectItem(root, "Seed");
			cJSON* cj_schedule = cJSON_GetObjectItem(root, "Schedule");

			if(cj_visible_type && cj_hidden_type &&
				cj_hidden_count && cj_minibatch_size &&
				cj_schedule)
			{
				ContrastiveDivergence::ModelConfig model_config;
				uint32_t minibatch_size = 0;
				int32_t seed = 1;

				for(int func = 0; func < ActivationFunction::Count; func++)
				{
					if(strcmp(cj_visible_type->valuestring, ActivationFunctionNames[func]) == 0)
					{
						model_config.VisibleType = (ActivationFunction_t)func;
					}

					if(strcmp(cj_hidden_type->valuestring, ActivationFunctionNames[func]) == 0)
					{
						model_config.HiddenType = (ActivationFunction_t)func;
					}
				}

				// make sure we found both activation functions
				if(model_config.VisibleType == -1 || model_config.HiddenType == -1)
				{
					goto Error;
				}

				if(cj_visible_count->valueint > 0)
				{
					model_config.VisibleUnits = cj_visible_count->valueint;
				}
				else
				{
					goto Error;
				}

				if(cj_hidden_count->valueint > 0)
				{
					model_config.HiddenUnits = cj_hidden_count->valueint;
				}
				else
				{
					goto Error;
				}

				if(cj_seed != nullptr)
				{
					seed = cj_seed->valueint;
				}

				if(cj_minibatch_size->valueint > 0)
				{
					minibatch_size = cj_minibatch_size->valueint;
				}
				else
				{
					goto Error;
				}

				// now step through schedule array
				std::vector<std::pair<ContrastiveDivergence::TrainingConfig, uint32_t>> schedule;
				CD::TrainingConfig train_config;
				uint32_t epochs;
				const int schedule_length = cJSON_GetArraySize(cj_schedule);
				if(schedule_length == 0)
				{
					goto Error;
				}
				for(int k = 0; k < schedule_length; k++)
				{
					cJSON* cj_train_config = cJSON_GetArrayItem(cj_schedule, k);

					cJSON* cj_epochs = cJSON_GetObjectItem(cj_train_config, "Epochs");
					cJSON* cj_learning_rate = cJSON_GetObjectItem(cj_train_config, "LearningRate");
					cJSON* cj_momentum = cJSON_GetObjectItem(cj_train_config, "Momentum");
					cJSON* cj_l1 = cJSON_GetObjectItem(cj_train_config, "L1Regularization");
					cJSON* cj_l2 = cJSON_GetObjectItem(cj_train_config, "L2Regularization");
					cJSON* cj_visible_dropout = cJSON_GetObjectItem(cj_train_config, "VisibleDropout");
					cJSON* cj_hidden_dropout = cJSON_GetObjectItem(cj_train_config, "HiddenDropout");
					cJSON* cj_adadelta_decay = cJSON_GetObjectItem(cj_train_config, "AdadeltaDecay");

					// epochs is the only thing required
					if(cj_epochs && cj_epochs->valueint > 0)
					{
						epochs = cj_epochs->valueint;
					}
					else
					{
						goto Error;
					}

					// the rest are optional

					if(cj_learning_rate)
					{
						if(cj_learning_rate->valuedouble >= 0.0)
						{
							train_config.LearningRate = (float)cj_learning_rate->valuedouble;
						}
						else
						{
							goto Error;
						}
					}
					if(cj_momentum)
					{
						if(cj_momentum->valuedouble >= 0.0 && cj_momentum->valuedouble < 1.0)
						{
							train_config.Momentum = (float)cj_momentum->valuedouble;
						}
						else
						{
							goto Error;
						}

					}
					if(cj_l1)
					{
						if(cj_l1->valuedouble >= 0.0)
						{
							train_config.L1Regularization = (float)cj_l1->valuedouble;
						}
						else
						{
							goto Error;
						}
					}
					if(cj_l2)
					{
						if(cj_l2->valuedouble >= 0.0)
						{
							train_config.L2Regularization = (float)cj_l2->valuedouble;
						}
						else
						{
							goto Error;
						}
					}
					if(cj_visible_dropout)
					{
						if(cj_visible_dropout->valuedouble >= 0.0 && cj_visible_dropout->valuedouble < 1.0)
						{
							train_config.VisibleDropout = (float)cj_visible_dropout->valuedouble;
						}
						else
						{
							goto Error;
						}
					}
					if(cj_hidden_dropout)
					{
						if(cj_hidden_dropout->valuedouble >= 0.0 && cj_hidden_dropout->valuedouble < 1.0)
						{
							train_config.HiddenDropout = (float)cj_hidden_dropout->valuedouble;
						}
						else
						{
							goto Error;
						}
					}
					if(cj_adadelta_decay)
					{
						if(cj_adadelta_decay->valuedouble >= 0.0 && cj_adadelta_decay->valuedouble < 1.0)
						{
							train_config.AdadeltaDecay = (float)cj_adadelta_decay->valuedouble;
						}
					}

					// save off this schedule and epoch count
					schedule.push_back(std::pair<CD::TrainingConfig, uint32_t>(train_config, epochs));
				}

				// finally construct our training schedule
				result = new TrainingSchedule<ContrastiveDivergence>(model_config, minibatch_size, seed);
				for(uint32_t k = 0; k < schedule.size(); k++)
				{
					result->AddTrainingConfig(schedule[k].first, schedule[k].second);
				}
			}
		}
Error:
		cJSON_Delete(root);
		return result;
	}

	template<>
	TrainingSchedule<BackPropagation>* TrainingSchedule<BackPropagation>::FromJSON(const std::string& json)
	{
		TrainingSchedule<BackPropagation>* result = nullptr;
		BackPropagation::ModelConfig model_config;
		uint32_t minibatch_size;
		int32_t seed = 1;

		std::vector<std::pair<BackPropagation::TrainingConfig, uint32_t>> schedule;

		cJSON* root = cJSON_Parse(json.c_str());
		if(root)
		{
			cJSON* cj_type = cJSON_GetObjectItem(root, "Type");
			if(!cj_type || (strcmp(cj_type->valuestring, "MLP") != 0 && strcmp(cj_type->valuestring, "MultilayerPerceptron") != 0))
			{
				goto Error;
			}

			cJSON* cj_layers = cJSON_GetObjectItem(root, "Layers");
			cJSON* cj_activation_functions = cJSON_GetObjectItem(root, "ActivationFunctions");
			cJSON* cj_minibatch_size = cJSON_GetObjectItem(root, "MinibatchSize");
			cJSON* cj_seed = cJSON_GetObjectItem(root, "Seed");
			cJSON* cj_schedule = cJSON_GetObjectItem(root, "Schedule");

			// make sure we have the mandatory bits
			if(cj_layers && cj_activation_functions &&
			   cj_minibatch_size && cj_schedule)
			{
				// verify we hae the right number of layer values and activation function values
				if(cJSON_GetArraySize(cj_layers) > 1 && cJSON_GetArraySize(cj_layers) == (cJSON_GetArraySize(cj_activation_functions) + 1))
				{
					// get our array iterators and populate the model config
					cJSON* cj_layer_val;
					cJSON* cj_func_val;

					cj_layer_val = cJSON_GetArrayItem(cj_layers, 0);
					model_config.InputCount = cj_layer_val->valueint;

					// parse network structure/functions
					for(int k = 0; k < cJSON_GetArraySize(cj_activation_functions); k++)
					{
						cj_layer_val = cJSON_GetArrayItem(cj_layers, k + 1);
						cj_func_val = cJSON_GetArrayItem(cj_activation_functions, k);

						if(cj_layer_val && cj_func_val)
						{
							BackPropagation::LayerConfig layer_config;
							layer_config.OutputUnits = cj_layer_val->valueint;
							layer_config.Function = ParseFunction(cj_func_val->valuestring);

							if(cj_layer_val->valueint < 1)
							{
								goto Error;
							}
							if(layer_config.Function == ActivationFunction::Invalid)
							{
								goto Error;
							}

							model_config.LayerConfigs.push_back(layer_config);
						}
						else
						{
							goto Error;
						}
					}

					if(cj_seed != nullptr)
					{
						seed = cj_seed->valueint;
					}

					// minibatch size
					if(cj_minibatch_size->valueint < 1)
					{
						goto Error;
					}
					minibatch_size = cj_minibatch_size->valueint;

					// parse our schedules
					if(cJSON_GetArraySize(cj_schedule) == 0)
					{
						goto Error;
					}

					BackPropagation::TrainingConfig train_config;
					uint32_t layer_count = model_config.LayerConfigs.size();
					for(uint32_t  k = 0; k < layer_count; k++)
					{
						BackPropagation::LayerParameters layer_params;;
						train_config.Parameters.push_back(layer_params);
					}

					// now read each traing config in the schedule
					for(int k = 0; k < cJSON_GetArraySize(cj_schedule); k++)
					{
						cJSON* cj_train_config = cJSON_GetArrayItem(cj_schedule, k);

						// this function will read an object and if it's an array, populate each member of the array to the appropriate layer config
						// if it is a single value, all the values in the array are given that value
						auto read_params = [&] (uint32_t index, const char* param, float min, float max) -> bool
						{
							cJSON* cj_param = cJSON_GetObjectItem(cj_train_config, param);
							if(cj_param)
							{
								if(cj_param->type == cJSON_Array)
								{
									// ensure we have the right number of params
									if(cJSON_GetArraySize(cj_param) != layer_count)
									{
										return false;
									}

									for(uint32_t j = 0; j < layer_count; j++)
									{
										cJSON* cj_val = cJSON_GetArrayItem(cj_param, j);
										if(cj_val->type != cJSON_Number)
										{
											return false;
										}

										float val = float(cj_val->valuedouble);

										if(val < min || val > max)
										{
											return false;
										}

										train_config.Parameters[j].Data[index] = val;

									}
								}
								else if(cj_param->type == cJSON_Number)
								{
									for(uint32_t j = 0; j < layer_count; j++)
									{
										float val = float(cj_param->valuedouble);

										if(val < min || val > max)
										{
											return false;
										}

										train_config.Parameters[j].Data[index] = val;
									}
								}
							}
							return true;
						};
#						define GET_INDEX(NAME) (((uint32_t)( &( (BackPropagation::LayerParameters*)(void*)0)->NAME) )/sizeof(float))
#						define READ_PARAMS(NAME, MIN, MAX) if(read_params(GET_INDEX(NAME), #NAME, MIN, MAX) == false) goto Error;

						READ_PARAMS(LearningRate, 0.0f, FLT_MAX)
						READ_PARAMS(Momentum, 0.0f, 1.0f)
						READ_PARAMS(L1Regularization, 0.0f, FLT_MAX)
						READ_PARAMS(L2Regularization, 0.0f, FLT_MAX)
						READ_PARAMS(Dropout, 0.0f, 1.0f)
						READ_PARAMS(Noise, 0.0f, FLT_MAX)
						READ_PARAMS(AdadeltaDecay, 0.0f, 1.0f)

						//now get the number of epochs
						cJSON* cj_epochs = cJSON_GetObjectItem(cj_train_config, "Epochs");
						if(cj_epochs == nullptr || cj_epochs->type != cJSON_Number || cj_epochs->valueint < 1)
						{
							goto Error;
						}
						uint32_t epochs = cj_epochs->valueint;
						schedule.push_back(std::pair<BackPropagation::TrainingConfig, uint32_t>(train_config, epochs));
					}
				}
				else
				{
					goto Error;
				}
			}
			else
			{
				goto Error;
			}
		}
		else
		{
			goto Error;
		}

		// create result here
		result = new TrainingSchedule<BackPropagation>(model_config, minibatch_size, seed);
		for(uint32_t k = 0; k < schedule.size(); k++)
		{
			result->AddTrainingConfig(schedule[k].first, schedule[k].second);
		}
Error:
		cJSON_Delete(root);
		return result;
	}

	template<>
	TrainingSchedule<AutoEncoderBackPropagation>* TrainingSchedule<AutoEncoderBackPropagation>::FromJSON(const std::string& json)
	{
		TrainingSchedule<AutoEncoderBackPropagation>* result = nullptr;

		cJSON* root = cJSON_Parse(json.c_str());
		if(root)
		{
			cJSON* cj_type = cJSON_GetObjectItem(root, "Type");

			if(!cj_type || strcmp(cj_type->valuestring, "AutoEncoder") != 0)
			{
				goto Error;
			}

			cJSON* cj_visible_count = cJSON_GetObjectItem(root, "VisibleCount");
			cJSON* cj_hidden_count = cJSON_GetObjectItem(root, "HiddenCount");
			cJSON* cj_hidden_type = cJSON_GetObjectItem(root, "HiddenType");
			cJSON* cj_output_type = cJSON_GetObjectItem(root, "OutputType");
			cJSON* cj_minibatch_size = cJSON_GetObjectItem(root, "MinibatchSize");
			cJSON* cj_seed = cJSON_GetObjectItem(root, "Seed");
			cJSON* cj_schedule = cJSON_GetObjectItem(root, "Schedule");

			if(cj_output_type && cj_hidden_type &&
				cj_hidden_count && cj_minibatch_size &&
				cj_schedule)
			{
				AutoEncoderBackPropagation::ModelConfig model_config;
				uint32_t minibatch_size = 0;
				int32_t seed = 1;

				for(int func = 0; func < ActivationFunction::Count; func++)
				{
					if(strcmp(cj_hidden_type->valuestring, ActivationFunctionNames[func]) == 0)
					{
						model_config.HiddenType = (ActivationFunction_t)func;
					}

					if(strcmp(cj_output_type->valuestring, ActivationFunctionNames[func]) == 0)
					{
						model_config.OutputType = (ActivationFunction_t)func;
					}
				}

				// make sure we found both activation functions
				if(model_config.HiddenType == -1 || model_config.OutputType == -1)
				{
					goto Error;
				}

				if(cj_visible_count->valueint > 0)
				{
					model_config.VisibleCount = cj_visible_count->valueint;
				}
				else
				{
					goto Error;
				}

				if(cj_hidden_count->valueint > 0)
				{
					model_config.HiddenCount = cj_hidden_count->valueint;
				}
				else
				{
					goto Error;
				}

				if(cj_seed != nullptr)
				{
					seed = cj_seed->valueint;
				}

				if(cj_minibatch_size->valueint > 0)
				{
					minibatch_size = cj_minibatch_size->valueint;
				}
				else
				{
					goto Error;
				}

				// now step through schedule array
				std::vector<std::pair<AutoEncoderBackPropagation::TrainingConfig, uint32_t>> schedule;
				AutoEncoderBackPropagation::TrainingConfig train_config;
				uint32_t epochs;
				const int schedule_length = cJSON_GetArraySize(cj_schedule);
				if(schedule_length == 0)
				{
					goto Error;
				}
				for(int k = 0; k < schedule_length; k++)
				{
					cJSON* cj_train_config = cJSON_GetArrayItem(cj_schedule, k);

					cJSON* cj_epochs = cJSON_GetObjectItem(cj_train_config, "Epochs");
					cJSON* cj_learning_rate = cJSON_GetObjectItem(cj_train_config, "LearningRate");
					cJSON* cj_momentum = cJSON_GetObjectItem(cj_train_config, "Momentum");
					cJSON* cj_l1 = cJSON_GetObjectItem(cj_train_config, "L1Regularization");
					cJSON* cj_l2 = cJSON_GetObjectItem(cj_train_config, "L2Regularization");
					cJSON* cj_visible_dropout = cJSON_GetObjectItem(cj_train_config, "VisibleDropout");
					cJSON* cj_hidden_dropout = cJSON_GetObjectItem(cj_train_config, "HiddenDropout");
					cJSON* cj_adadelta_decay = cJSON_GetObjectItem(cj_train_config, "AdadeltaDecay");

					// epochs is the only thing required
					if(cj_epochs && cj_epochs->valueint > 0)
					{
						epochs = cj_epochs->valueint;
					}
					else
					{
						goto Error;
					}

					// the rest are optional

					if(cj_learning_rate)
					{
						if(cj_learning_rate->valuedouble >= 0.0)
						{
							train_config.LearningRate = (float)cj_learning_rate->valuedouble;
						}
						else
						{
							goto Error;
						}
					}
					if(cj_momentum)
					{
						if(cj_momentum->valuedouble >= 0.0 && cj_momentum->valuedouble < 1.0)
						{
							train_config.Momentum = (float)cj_momentum->valuedouble;
						}
						else
						{
							goto Error;
						}

					}
					if(cj_l1)
					{
						if(cj_l1->valuedouble >= 0.0)
						{
							train_config.L1Regularization = (float)cj_l1->valuedouble;
						}
						else
						{
							goto Error;
						}
					}
					if(cj_l2)
					{
						if(cj_l2->valuedouble >= 0.0)
						{
							train_config.L2Regularization = (float)cj_l2->valuedouble;
						}
						else
						{
							goto Error;
						}
					}
					if(cj_visible_dropout)
					{
						if(cj_visible_dropout->valuedouble >= 0.0 && cj_visible_dropout->valuedouble < 1.0)
						{
							train_config.VisibleDropout = (float)cj_visible_dropout->valuedouble;
						}
						else
						{
							goto Error;
						}
					}
					if(cj_hidden_dropout)
					{
						if(cj_hidden_dropout->valuedouble >= 0.0 && cj_hidden_dropout->valuedouble < 1.0)
						{
							train_config.HiddenDropout = (float)cj_hidden_dropout->valuedouble;
						}
						else
						{
							goto Error;
						}
					}
					if(cj_adadelta_decay)
					{
						if(cj_adadelta_decay->valuedouble >= 0.0 && cj_adadelta_decay->valuedouble < 1.0)
						{
							train_config.AdadeltaDecay = (float)cj_adadelta_decay->valuedouble;
						}
					}

					// save off this schedule and epoch count
					schedule.push_back(std::pair<AutoEncoderBackPropagation::TrainingConfig, uint32_t>(train_config, epochs));
				}

				// finally construct our training schedule
				result = new TrainingSchedule<AutoEncoderBackPropagation>(model_config, minibatch_size, seed);
				for(uint32_t k = 0; k < schedule.size(); k++)
				{
					result->AddTrainingConfig(schedule[k].first, schedule[k].second);
				}
			}
		}
Error:
		cJSON_Delete(root);
		return result;
	}
}


text:
'use strict';

angular.module('cropNodeApp')
  .factory('Session', function ($resource) {
    return $resource('/api/session/');
  });


text:
using namespace Math;

class Model
{
public:

    Model();
    ~Model();

    void Clear();

    enum
    {
        attrib_mask_0 = (1 << 0),
        attrib_mask_1 = (1 << 1),
        attrib_mask_2 = (1 << 2),
        attrib_mask_3 = (1 << 3),
        attrib_mask_4 = (1 << 4),
        attrib_mask_5 = (1 << 5),
        attrib_mask_6 = (1 << 6),
        attrib_mask_7 = (1 << 7),
        attrib_mask_8 = (1 << 8),
        attrib_mask_9 = (1 << 9),
        attrib_mask_10 = (1 << 10),
        attrib_mask_11 = (1 << 11),
        attrib_mask_12 = (1 << 12),
        attrib_mask_13 = (1 << 13),
        attrib_mask_14 = (1 << 14),
        attrib_mask_15 = (1 << 15),

        // friendly name aliases
        attrib_mask_position = attrib_mask_0,
        attrib_mask_texcoord0 = attrib_mask_1,
        attrib_mask_normal = attrib_mask_2,
        attrib_mask_tangent = attrib_mask_3,
        attrib_mask_bitangent = attrib_mask_4,
    };

    enum
    {
        attrib_0 = 0,
        attrib_1 = 1,
        attrib_2 = 2,
        attrib_3 = 3,
        attrib_4 = 4,
        attrib_5 = 5,
        attrib_6 = 6,
        attrib_7 = 7,
        attrib_8 = 8,
        attrib_9 = 9,
        attrib_10 = 10,
        attrib_11 = 11,
        attrib_12 = 12,
        attrib_13 = 13,
        attrib_14 = 14,
        attrib_15 = 15,

        // friendly name aliases
        attrib_position = attrib_0,
        attrib_texcoord0 = attrib_1,
        attrib_normal = attrib_2,
        attrib_tangent = attrib_3,
        attrib_bitangent = attrib_4,

        maxAttribs = 16
    };

    enum
    {
        attrib_format_none = 0,
        attrib_format_ubyte,
        attrib_format_byte,
        attrib_format_ushort,
        attrib_format_short,
        attrib_format_float,

        attrib_formats
    };

    struct BoundingBox
    {
        Vector3 min;
        Vector3 max;
    };

    struct Header
    {
        uint32_t meshCount;
        uint32_t materialCount;
        uint32_t vertexDataByteSize;
        uint32_t indexDataByteSize;
        uint32_t vertexDataByteSizeDepth;
        BoundingBox boundingBox;
    };
    Header m_Header;

	struct Attrib
	{
		uint16_t offset; // byte offset from the start of the vertex
		uint16_t normalized; // if true, integer formats are interpreted as [-1, 1] or [0, 1]
		uint16_t components; // 1-4
		uint16_t format;
	};
	struct Mesh
    {
        BoundingBox boundingBox;

        unsigned int materialIndex;

        unsigned int attribsEnabled;
        unsigned int attribsEnabledDepth;
        unsigned int vertexStride;
        unsigned int vertexStrideDepth;
        Attrib attrib[maxAttribs];
        Attrib attribDepth[maxAttribs];

        unsigned int vertexDataByteOffset;
        unsigned int vertexCount;
        unsigned int indexDataByteOffset;
        unsigned int indexCount;

        unsigned int vertexDataByteOffsetDepth;
        unsigned int vertexCountDepth;
    };
    Mesh *m_pMesh;

    struct Material
    {
        Vector3 diffuse;
        Vector3 specular;
        Vector3 ambient;
        Vector3 emissive;
        Vector3 transparent; // light passing through a transparent surface is multiplied by this filter color
        float opacity;
        float shininess; // specular exponent
        float specularStrength; // multiplier on top of specular color

        enum {maxTexPath = 128};
        enum {texCount = 6};
        char texDiffusePath[maxTexPath];
        char texSpecularPath[maxTexPath];
        char texEmissivePath[maxTexPath];
        char texNormalPath[maxTexPath];
        char texLightmapPath[maxTexPath];
        char texReflectionPath[maxTexPath];

        enum {maxMaterialName = 128};
        char name[maxMaterialName];
    };
    Material *m_pMaterial;

    unsigned char *m_pVertexData;
    unsigned char *m_pIndexData;
    StructuredBuffer m_VertexBuffer;
    ByteAddressBuffer m_IndexBuffer;
    uint32_t m_VertexStride;

    // optimized for depth-only rendering
    unsigned char *m_pVertexDataDepth;
    unsigned char *m_pIndexDataDepth;
    StructuredBuffer m_VertexBufferDepth;
    ByteAddressBuffer m_IndexBufferDepth;
    uint32_t m_VertexStrideDepth;

	virtual bool Load(const char* filename)
	{
		return LoadH3D(filename);
	}

	const BoundingBox& GetBoundingBox() const
	{
		return m_Header.boundingBox;
	}

    D3D12_CPU_DESCRIPTOR_HANDLE* GetSRVs( uint32_t materialIdx ) const
    {
        return m_SRVs + materialIdx * 6;
    }

protected:

	bool LoadH3D(const char *filename);
	bool SaveH3D(const char *filename) const;

	void ComputeMeshBoundingBox(unsigned int meshIndex, BoundingBox &bbox) const;
	void ComputeGlobalBoundingBox(BoundingBox &bbox) const;
	void ComputeAllBoundingBoxes();

    void ReleaseTextures();
    void LoadTextures();
    D3D12_CPU_DESCRIPTOR_HANDLE* m_SRVs;
};


text:
/* global $, APP, JitsiMeetJS */
/* jshint -W101 */
import Avatar from "../avatar/Avatar";
import UIUtil from "../util/UIUtil";

const RTCUIHelper = JitsiMeetJS.util.RTCUIHelper;

function SmallVideo(VideoLayout) {
    this.isMuted = false;
    this.hasAvatar = false;
    this.isVideoMuted = false;
    this.videoStream = null;
    this.audioStream = null;
    this.VideoLayout = VideoLayout;
}

function setVisibility(selector, show) {
    if (selector && selector.length > 0) {
        selector.css("visibility", show ? "visible" : "hidden");
    }
}

/**
 * Returns the identifier of this small video.
 *
 * @returns the identifier of this small video
 */
SmallVideo.prototype.getId = function () {
    return this.id;
};

/* Indicates if this small video is currently visible.
 *
 * @return <tt>true</tt> if this small video isn't currently visible and
 * <tt>false</tt> - otherwise.
 */
SmallVideo.prototype.isVisible = function () {
    return $('#' + this.videoSpanId).is(':visible');
};

SmallVideo.prototype.showDisplayName = function(isShow) {
    var nameSpan = $('#' + this.videoSpanId + '>span.displayname').get(0);
    if (isShow) {
        if (nameSpan && nameSpan.innerHTML && nameSpan.innerHTML.length)
            nameSpan.setAttribute("style", "display:inline-block;");
    }
    else {
        if (nameSpan)
            nameSpan.setAttribute("style", "display:none;");
    }
};

/**
 * Enables / disables the device availability icons for this small video.
 * @param {enable} set to {true} to enable and {false} to disable
 */
SmallVideo.prototype.enableDeviceAvailabilityIcons = function (enable) {
    if (typeof enable === "undefined")
        return;

    this.deviceAvailabilityIconsEnabled = enable;
};

/**
 * Sets the device "non" availability icons.
 * @param devices the devices, which will be checked for availability
 */
SmallVideo.prototype.setDeviceAvailabilityIcons = function (devices) {
    if (!this.deviceAvailabilityIconsEnabled)
        return;

    if(!this.container)
        return;

    var noMic = $("#" + this.videoSpanId + " > .noMic");
    var noVideo =  $("#" + this.videoSpanId + " > .noVideo");

    noMic.remove();
    noVideo.remove();
    if (!devices.audio) {
        this.container.appendChild(
            document.createElement("div")).setAttribute("class", "noMic");
    }

    if (!devices.video) {
        this.container.appendChild(
            document.createElement("div")).setAttribute("class", "noVideo");
    }

    if (!devices.audio && !devices.video) {
        noMic.css("background-position", "75%");
        noVideo.css("background-position", "25%");
        noVideo.css("background-color", "transparent");
    }
};

/**
 * Sets the type of the video displayed by this instance.
 * @param videoType 'camera' or 'desktop'
 */
SmallVideo.prototype.setVideoType = function (videoType) {
    this.videoType = videoType;
};

/**
 * Returns the type of the video displayed by this instance.
 * @returns {String} 'camera', 'screen' or undefined.
 */
SmallVideo.prototype.getVideoType = function () {
    return this.videoType;
};

/**
 * Shows the presence status message for the given video.
 */
SmallVideo.prototype.setPresenceStatus = function (statusMsg) {
    if (!this.container) {
        // No container
        return;
    }

    var statusSpan = $('#' + this.videoSpanId + '>span.status');
    if (!statusSpan.length) {
        //Add status span
        statusSpan = document.createElement('span');
        statusSpan.className = 'status';
        statusSpan.id = this.videoSpanId + '_status';
        $('#' + this.videoSpanId)[0].appendChild(statusSpan);

        statusSpan = $('#' + this.videoSpanId + '>span.status');
    }

    // Display status
    if (statusMsg && statusMsg.length) {
        $('#' + this.videoSpanId + '_status').text(statusMsg);
        statusSpan.get(0).setAttribute("style", "display:inline-block;");
    }
    else {
        // Hide
        statusSpan.get(0).setAttribute("style", "display:none;");
    }
};

/**
 * Creates an audio or video element for a particular MediaStream.
 */
SmallVideo.createStreamElement = function (stream) {
    let isVideo = stream.isVideoTrack();

    let element = isVideo
        ? document.createElement('video')
        : document.createElement('audio');
    if (isVideo) {
        element.setAttribute("muted", "true");
    }

    RTCUIHelper.setAutoPlay(element, true);

    element.id = SmallVideo.getStreamElementID(stream);

    element.onplay = function () {
        var type = (isVideo ? 'video' : 'audio');
        var now = APP.connectionTimes[type + ".render"]
            = window.performance.now();
        console.log("(TIME) Render " + type + ":\t",
                    now);
    };

    element.oncontextmenu = function () { return false; };

    return element;
};

/**
 * Returns the element id for a particular MediaStream.
 */
SmallVideo.getStreamElementID = function (stream) {
    let isVideo = stream.isVideoTrack();

    return (isVideo ? 'remoteVideo_' : 'remoteAudio_') + stream.getId();
};

/**
 * Configures hoverIn/hoverOut handlers.
 */
SmallVideo.prototype.bindHoverHandler = function () {
    // Add hover handler
    var self = this;
    $(this.container).hover(
        function () {
            self.showDisplayName(true);
        },
        function () {
            // If the video has been "pinned" by the user we want to
            // keep the display name on place.
            if (!self.VideoLayout.isLargeVideoVisible() ||
                !self.VideoLayout.isCurrentlyOnLarge(self.id))
                self.showDisplayName(false);
        }
    );
};

/**
 * Updates the data for the indicator
 * @param id the id of the indicator
 * @param percent the percent for connection quality
 * @param object the data
 */
SmallVideo.prototype.updateStatsIndicator = function (percent, object) {
    if(this.connectionIndicator)
        this.connectionIndicator.updateConnectionQuality(percent, object);
};

SmallVideo.prototype.hideIndicator = function () {
    if(this.connectionIndicator)
        this.connectionIndicator.hideIndicator();
};

/**
 * Shows audio muted indicator over small videos.
 * @param {string} isMuted
 */
SmallVideo.prototype.showAudioIndicator = function(isMuted) {
    var audioMutedSpan = $('#' + this.videoSpanId + '>span.audioMuted');

    if (!isMuted) {
        if (audioMutedSpan.length > 0) {
            audioMutedSpan.popover('hide');
            audioMutedSpan.remove();
        }
    }
    else {
        if (!audioMutedSpan.length) {
            audioMutedSpan = document.createElement('span');
            audioMutedSpan.className = 'audioMuted';
            UIUtil.setTooltip(audioMutedSpan,
                "videothumbnail.mute",
                "top");

            this.container.appendChild(audioMutedSpan);
            APP.translation.translateElement($('#' + this.videoSpanId + " > span"));
            var mutedIndicator = document.createElement('i');
            mutedIndicator.className = 'icon-mic-disabled';
            audioMutedSpan.appendChild(mutedIndicator);

        }
        this.updateIconPositions();
    }
    this.isMuted = isMuted;
};

/**
 * Shows video muted indicator over small videos and disables/enables avatar
 * if video muted.
 */
SmallVideo.prototype.setMutedView = function(isMuted) {
    this.isVideoMuted = isMuted;
    this.updateView();

    var videoMutedSpan = $('#' + this.videoSpanId + '>span.videoMuted');

    if (isMuted === false) {
        if (videoMutedSpan.length > 0) {
            videoMutedSpan.remove();
        }
    }
    else {
        if (!videoMutedSpan.length) {
            videoMutedSpan = document.createElement('span');
            videoMutedSpan.className = 'videoMuted';

            this.container.appendChild(videoMutedSpan);

            var mutedIndicator = document.createElement('i');
            mutedIndicator.className = 'icon-camera-disabled';
            UIUtil.setTooltip(mutedIndicator,
                "videothumbnail.videomute",
                "top");
            videoMutedSpan.appendChild(mutedIndicator);
            //translate texts for muted indicator
            APP.translation.translateElement($('#' + this.videoSpanId  + " > span > i"));
        }

        this.updateIconPositions();
    }
};

SmallVideo.prototype.updateIconPositions = function () {
    var audioMutedSpan = $('#' + this.videoSpanId + '>span.audioMuted');
    var connectionIndicator = $('#' + this.videoSpanId + '>div.connectionindicator');
    var videoMutedSpan = $('#' + this.videoSpanId + '>span.videoMuted');
    if(connectionIndicator.length > 0 &&
        connectionIndicator[0].style.display != "none") {
        audioMutedSpan.css({right: "23px"});
        videoMutedSpan.css({right: ((audioMutedSpan.length > 0? 23 : 0) + 30) + "px"});
    } else {
        audioMutedSpan.css({right: "0px"});
        videoMutedSpan.css({right: (audioMutedSpan.length > 0? 30 : 0) + "px"});
    }
};

/**
 * Creates the element indicating the moderator(owner) of the conference.
 *
 * @param parentElement the parent element where the owner indicator will
 * be added
 */
SmallVideo.prototype.createModeratorIndicatorElement = function () {
    // Show moderator indicator
    var indicatorSpan = $('#' + this.videoSpanId + ' .focusindicator');

    if (!indicatorSpan || indicatorSpan.length === 0) {
        indicatorSpan = document.createElement('span');
        indicatorSpan.className = 'focusindicator';

        this.container.appendChild(indicatorSpan);
        indicatorSpan = $('#' + this.videoSpanId + ' .focusindicator');
    }

    if (indicatorSpan.children().length !== 0)
        return;
    var moderatorIndicator = document.createElement('i');
    moderatorIndicator.className = 'fa fa-star';
    indicatorSpan[0].appendChild(moderatorIndicator);

    UIUtil.setTooltip(indicatorSpan[0],
        "videothumbnail.moderator",
        "top");

    //translates text in focus indicators
    APP.translation.translateElement($('#' + this.videoSpanId + ' .focusindicator'));
};

SmallVideo.prototype.selectVideoElement = function () {
    return $(RTCUIHelper.findVideoElement($('#' + this.videoSpanId)[0]));
};

/**
 * Enables / disables the css responsible for focusing/pinning a video
 * thumbnail.
 *
 * @param isFocused indicates if the thumbnail should be focused/pinned or not
 */
SmallVideo.prototype.focus = function(isFocused) {
    var focusedCssClass = "videoContainerFocused";
    var isFocusClassEnabled = $(this.container).hasClass(focusedCssClass);

    if (!isFocused && isFocusClassEnabled) {
        $(this.container).removeClass(focusedCssClass);
    }
    else if (isFocused && !isFocusClassEnabled) {
        $(this.container).addClass(focusedCssClass);
    }
};

SmallVideo.prototype.hasVideo = function () {
    return this.selectVideoElement().length !== 0;
};

/**
 * Hides or shows the user's avatar.
 * This update assumes that large video had been updated and we will
 * reflect it on this small video.
 *
 * @param show whether we should show the avatar or not
 * video because there is no dominant speaker and no focused speaker
 */
SmallVideo.prototype.updateView = function () {
    if (!this.hasAvatar) {
        if (this.id) {
            // Init avatar
            this.avatarChanged(Avatar.getAvatarUrl(this.id));
        } else {
            console.error("Unable to init avatar - no id", this);
            return;
        }
    }

    let video = this.selectVideoElement();

    let avatar = $(`#avatar_${this.id}`);

    var isCurrentlyOnLarge = this.VideoLayout.isCurrentlyOnLarge(this.id);

    var showVideo = !this.isVideoMuted && !isCurrentlyOnLarge;
    var showAvatar;
    if ((!this.isLocal
            && !this.VideoLayout.isInLastN(this.id))
        || this.isVideoMuted) {
        showAvatar = true;
    } else {
        // We want to show the avatar when the video is muted or not exists
        // that is when 'true' or 'null' is returned
        showAvatar = !this.videoStream || this.videoStream.isMuted();
    }

    showAvatar = showAvatar && !isCurrentlyOnLarge;

    if (video && video.length > 0) {
        setVisibility(video, showVideo);
    }
    setVisibility(avatar, showAvatar);

    this.showDisplayName(!showVideo && !showAvatar);
};

SmallVideo.prototype.avatarChanged = function (avatarUrl) {
    var thumbnail = $('#' + this.videoSpanId);
    var avatar = $('#avatar_' + this.id);
    this.hasAvatar = true;

    // set the avatar in the thumbnail
    if (avatar && avatar.length > 0) {
        avatar[0].src = avatarUrl;
    } else {
        if (thumbnail && thumbnail.length > 0) {
            avatar = document.createElement('img');
            avatar.id = 'avatar_' + this.id;
            avatar.className = 'userAvatar';
            avatar.src = avatarUrl;
            thumbnail.append(avatar);
        }
    }
};

/**
 * Updates the Indicator for dominant speaker.
 *
 * @param isSpeaker indicates the current indicator state
 */
SmallVideo.prototype.updateDominantSpeakerIndicator = function (isSpeaker) {

    if (!this.container) {
        console.warn( "Unable to set dominant speaker indicator - "
            + this.videoSpanId + " does not exist");
        return;
    }

    var indicatorSpan
        = $('#' + this.videoSpanId + '>span.dominantspeakerindicator');

    // If we do not have an indicator for this video.
    if (indicatorSpan.length <= 0) {
        indicatorSpan = document.createElement('span');

        indicatorSpan.innerHTML
            = "<i id='speakerindicatoricon' class='fa fa-bullhorn'></i>";
        indicatorSpan.className = 'dominantspeakerindicator';

        $('#' + this.videoSpanId)[0].appendChild(indicatorSpan);

        // adds a tooltip
        UIUtil.setTooltip(indicatorSpan, "speaker", "left");
        APP.translation.translateElement($(indicatorSpan));
    }

    $(indicatorSpan).css("visibility", isSpeaker ? "visible" : "hidden");
};

export default SmallVideo;