示例#1
0
void drawHistos(TString rfile) {
  
  TH1::AddDirectory(0);

  TFile f(rfile);
  f.ls();
  TH1D *hpp = (TH1D*)f.Get("hpp");
  TH1D *hpn = (TH1D*)f.Get("hpn");
  TH1D *hnp = (TH1D*)f.Get("hnp");
  TH1D *hnn = (TH1D*)f.Get("hnn");

  hpp->Print();
  hnn->Print();
  hpn->Print();
  hnp->Print();
 
  TCanvas *cv = new TCanvas("cv", "Delta t", 500, 700);
  cv->Divide(1,2);
  
  cv->cd(1);
  drawOverlay(hpp, hnn);
  cv->cd(2);
  drawOverlay(hpn, hnp);

  f.Close();
}
示例#2
0
void Map::draw(Graphics *graphics, int scrollX, int scrollY)
{
    int endPixelY = graphics->getHeight() + scrollY + mTileHeight - 1;

    // TODO: Do this per-layer
    endPixelY += mMaxTileHeight - mTileHeight;

    int startX = scrollX / mTileWidth;
    int startY = scrollY / mTileHeight;
    int endX = (graphics->getWidth() + scrollX + mTileWidth - 1) / mTileWidth;
    int endY = endPixelY / mTileHeight;

    // Make sure sprites are sorted
    mSprites.sort(spriteCompare);

    // draw the game world
    Layers::const_iterator layeri = mLayers.begin();
    for (; layeri != mLayers.end(); ++layeri)
    {
        (*layeri)->draw(graphics,
                        startX, startY, endX, endY,
                        scrollX, scrollY,
                        mSprites);
    }

    drawOverlay(graphics, scrollX, scrollY,
            (int) config.getValue("OverlayDetail", 2));
}
示例#3
0
文件: plotter.cpp 项目: scottdm/gqrx
//////////////////////////////////////////////////////////////////////
// Called when screen size changes so must recalculate bitmaps
//////////////////////////////////////////////////////////////////////
void CPlotter::resizeEvent(QResizeEvent* )
{
    if (!size().isValid())
        return;

    if (m_Size != size())
    {	//if changed, resize pixmaps to new screensize
        m_Size = size();
        m_OverlayPixmap = QPixmap(m_Size.width(), m_Percent2DScreen*m_Size.height()/100);
        m_OverlayPixmap.fill(Qt::black);
        m_2DPixmap = QPixmap(m_Size.width(), m_Percent2DScreen*m_Size.height()/100);
        m_2DPixmap.fill(Qt::black);

        int height = (100-m_Percent2DScreen)*m_Size.height()/100;
        if (m_WaterfallPixmap.isNull()) {
            m_WaterfallPixmap = QPixmap(m_Size.width(), height);
            m_WaterfallPixmap.fill(Qt::black);
        } else {
            m_WaterfallPixmap = m_WaterfallPixmap.scaled(m_Size.width(), height,
                                                         Qt::IgnoreAspectRatio,
                                                         Qt::SmoothTransformation);
        }
    }
    drawOverlay();
}
示例#4
0
文件: plotter.cpp 项目: azorg/gqrx
void CPlotter::updateOverlay()
{
    if (m_Running)
        m_DrawOverlay = true;
    else
        drawOverlay();
}
示例#5
0
void GUIEngine::run()
{

	// Always create clouds because they may or may not be
	// needed based on the game selected
	video::IVideoDriver* driver = m_device->getVideoDriver();

	cloudInit();

	while(m_device->run() && (!m_startgame) && (!m_kill)) {
		driver->beginScene(true, true, video::SColor(255,140,186,250));

		if (m_clouds_enabled)
		{
			cloudPreProcess();
			drawOverlay(driver);
		}
		else
			drawBackground(driver);

		//drawHeader(driver);
		//drawFooter(driver);

		m_device->getGUIEnvironment()->drawAll();

		driver->endScene();

		if (m_clouds_enabled)
			cloudPostProcess();
		else
			sleep_ms(25);

		m_script->Step();
	}
}
示例#6
0
// Main display loop
void display () 
{
	cam.moveToPos ( glide.x, 0, 0  );
	glide.x *= 0.8;	
		
	PERF_PUSH ( "frame" );

	// Clear framebuffers. OpenGL
	glClearColor( 0.1, 0.1, 0.1, 0.0 );
	glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

	drawOverlay ();

	drawGui ();

	draw2D ();

	#ifdef USE_DX
		// DirectX - Swap buffers		
		checkHR ( g_pSwapChain->Present ( 0, 0 ) );
	#else
		// OpenGL - Swap buffers
		SwapBuffers ( g_hDC );  		
	#endif

	PERF_POP ();

	frame++;
}
示例#7
0
void RS_GraphicView::drawLayer3(RS_Painter *painter) {
	// drawing zero points:
	if (!isPrintPreview()) {
		drawRelativeZero(painter);
		drawOverlay(painter);
	}
}
示例#8
0
文件: plotter.cpp 项目: azorg/gqrx
//////////////////////////////////////////////////////////////////////
// Called when a mouse wheel is turned
//////////////////////////////////////////////////////////////////////
void CPlotter::wheelEvent(QWheelEvent * event)
{
    QPoint pt = event->pos();
    int numDegrees = event->delta() / 8;
    int numSteps = numDegrees / 15;  /** FIXME: Only used for direction **/

    /** FIXME: zooming could use some optimisation **/
    if (m_CursorCaptured == YAXIS)
    {
        // Vertical zoom. Wheel down: zoom out, wheel up: zoom in
        // During zoom we try to keep the point (dB or kHz) under the cursor fixed
        float zoom_fac = event->delta() < 0 ? 1.1 : 0.9;
        float ratio = (float)pt.y() / (float)m_OverlayPixmap.height();
        float db_range = (float)(m_MaxdB - m_MindB);
        float y_range = (float)m_OverlayPixmap.height();
        float db_per_pix = db_range / y_range;
        float fixed_db = m_MaxdB - pt.y() * db_per_pix;

        db_range = qBound(1.0f, db_range * zoom_fac, 2000.0f);

        m_MaxdB = fixed_db + ratio*db_range;
        m_MindB = m_MaxdB - db_range;

        m_PeakHoldValid = false;
    }
    else if (m_CursorCaptured == XAXIS)
    {
        zoomStepX(event->delta() < 0 ? 1.1 : 0.9, pt.x());
    }
    else if (event->modifiers() & Qt::ControlModifier)
    {
        // filter width
        m_DemodLowCutFreq -= numSteps*m_ClickResolution;
        m_DemodHiCutFreq += numSteps*m_ClickResolution;
        clampDemodParameters();
        emit newFilterFreq(m_DemodLowCutFreq, m_DemodHiCutFreq);
    }

    else if (event->modifiers() & Qt::ShiftModifier)
    {
        // filter shift
        m_DemodLowCutFreq += numSteps*m_ClickResolution;
        m_DemodHiCutFreq += numSteps*m_ClickResolution;
        clampDemodParameters();
        emit newFilterFreq(m_DemodLowCutFreq, m_DemodHiCutFreq);
    }
    else
    {
        // inc/dec demod frequency
        m_DemodCenterFreq += (numSteps*m_ClickResolution);
        m_DemodCenterFreq = roundFreq(m_DemodCenterFreq, m_ClickResolution );
        emit newDemodFreq(m_DemodCenterFreq, m_DemodCenterFreq-m_CenterFreq);
    }

    if (m_Running)
        m_DrawOverlay = true;
    else
        drawOverlay();
}
示例#9
0
文件: plotter.cpp 项目: scottdm/gqrx
/*! \brief Center FFT plot around the dmeodulator frequency. */
void CPlotter::moveToDemodFreq(void)
{
    setFftCenterFreq(m_DemodCenterFreq-m_CenterFreq);
    if (m_Running)
        m_DrawOverlay = true;
    else
        drawOverlay();
}
	COverlayBitmapManager::COverlayBitmapManager(DShowLib::Grabber *m_grabber)
		: m_Grabber(m_grabber)
	{
		setOverlayBitmapColorMode( OverlayBitmap::eBESTFIT );
		
		m_Grabber->setOverlayBitmapPathPosition( ePP_DEVICE );
		drawOverlay( ePP_DEVICE );
	}
示例#11
0
文件: plotter.cpp 项目: scottdm/gqrx
/*! \brief Center FFT plot around 0 (corresponds to center freq). */
void CPlotter::moveToCenterFreq(void)
{
    setFftCenterFreq(0);
    if (m_Running)
        m_DrawOverlay = true;
    else
        drawOverlay();
}
示例#12
0
文件: plotter.cpp 项目: scottdm/gqrx
/*! \brief Set upper limit of dB scale. */
void CPlotter::setMaxDB(double max)
{
    m_MaxdB = max;

    if (m_Running)
        m_DrawOverlay = true;
    else
        drawOverlay();
}
示例#13
0
文件: plotter.cpp 项目: scottdm/gqrx
/*! \brief Set lower limit of dB scale. */
void CPlotter::setMinDB(double min)
{
    m_MindB = min;

    if (m_Running)
        m_DrawOverlay = true;
    else
        drawOverlay();
}
void ScreenshotThumbView::paintEvent(QPaintEvent *pe)
{
    QGraphicsView::paintEvent(pe);
    if(hovered)
    {
        QPainter painter(viewport());
        drawOverlay(&painter, QColor(100,100,100,60));
        drawText(&painter, QColor(28,28,28,200), QColor(127,127,127,240));
    }
}
示例#15
0
文件: plotter.cpp 项目: azorg/gqrx
/*! \brief Center FFT plot around 0 (corresponds to center freq). */
void CPlotter::moveToCenterFreq(void)
{
    setFftCenterFreq(0);
    if (m_Running)
        m_DrawOverlay = true;
    else
        drawOverlay();

    m_PeakHoldValid = false;
}
示例#16
0
文件: plotter.cpp 项目: scottdm/gqrx
//////////////////////////////////////////////////////////////////////
// Called when a mouse button is pressed
//////////////////////////////////////////////////////////////////////
void CPlotter::mousePressEvent(QMouseEvent * event)
{
    QPoint pt = event->pos();

    if (NONE == m_CursorCaptured)
    {
        if (isPointCloseTo(pt.x(), m_DemodFreqX, m_CursorCaptureDelta))
        {	//in move demod box center frequency region
            m_CursorCaptured = CENTER;
            m_GrabPosition = pt.x()-m_DemodFreqX;
        }
        else if (isPointCloseTo(pt.x(), m_DemodLowCutFreqX, m_CursorCaptureDelta))
        {   // filter low cut
            m_CursorCaptured = LEFT;
            m_GrabPosition = pt.x()-m_DemodLowCutFreqX;
        }
        else if (isPointCloseTo(pt.x(), m_DemodHiCutFreqX, m_CursorCaptureDelta))
        {   // filter high cut
            m_CursorCaptured = RIGHT;
            m_GrabPosition = pt.x()-m_DemodHiCutFreqX;
        }
        else
        {
            if (event->buttons() == Qt::LeftButton)
            {
                //if cursor not captured set demod frequency and start demod box capture
                m_DemodCenterFreq = roundFreq(freqFromX(pt.x()),m_ClickResolution );
                emit newDemodFreq(m_DemodCenterFreq, m_DemodCenterFreq-m_CenterFreq);

                //save initial grab postion from m_DemodFreqX
                //setCursor(QCursor(Qt::CrossCursor));
                m_CursorCaptured = CENTER;
                m_GrabPosition = 1;
                //m_GrabPosition = pt.x()-m_DemodFreqX;
                drawOverlay();
            }
            else if (event->buttons() == Qt::MidButton)
            {
                // set center freq
                m_CenterFreq = roundFreq(freqFromX(pt.x()), m_ClickResolution);
                m_DemodCenterFreq = m_CenterFreq;
                emit newCenterFreq(m_CenterFreq);
                emit newDemodFreq(m_DemodCenterFreq, m_DemodCenterFreq-m_CenterFreq);
            }
        }
    }
    else
    {
        if (m_CursorCaptured == YAXIS)
            // get ready for moving Y axis
            m_Yzero = pt.y();
        else if (m_CursorCaptured == XAXIS)
            m_Xzero = pt.x();
    }
}
示例#17
0
文件: plotter.cpp 项目: azorg/gqrx
/*! \brief Set lower limit of dB scale. */
void CPlotter::setMinDB(float min)
{
    m_MindB = min;

    if (m_Running)
        m_DrawOverlay = true;
    else
        drawOverlay();

    m_PeakHoldValid = false;
}
示例#18
0
文件: main.cpp 项目: duxing/SmokeSim
void onDrawCb()
{
	// Keep track of time
	theFpsTracker.timestamp();

	// Draw Scene and overlay
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	theCamera.draw();
	theSmokeSim.draw(theCamera);
	drawOverlay();
	glutSwapBuffers();
}
示例#19
0
文件: plotter.cpp 项目: scottdm/gqrx
void CPlotter::setCenterFreq(quint64 f)
{
    qint64 offset = m_CenterFreq - m_DemodCenterFreq;

    m_CenterFreq = f;
    m_DemodCenterFreq = m_CenterFreq - offset;

    if (m_Running)
        m_DrawOverlay = true;
    else
        drawOverlay();
}
示例#20
0
//--------------------------------------------------------------
void MidiController::draw(ofEventArgs& args){
    
    if(bMapModeEnabled){
        ofPushStyle();
        ofEnableAlphaBlending();
        
        // draw the rectangles on top of the controls
        for(auto it = controls.begin(); it != controls.end(); ++it){
            string controlName = it->first;
            ofxBaseGui* control = it->second;
            
            if(controlName == selected){
                drawOverlay(control, colorHighlight, ofColor(255));
            }else{
                drawOverlay(control, colorNormal, ofColor(0));
            }
        }
        
        // draw the labels
        for(int ch = 0; ch < NUM_CHANNELS; ch++){
            for(int cc = 0; cc < NUM_CONTROLS; cc++){
                string name = midiMap[ch][cc];
                
                if(name != ""){
                    ofxBaseGui* control = controls[name];
                    ofRectangle r = control->getShape();
                    ofSetColor(255);
                    string text = ofToString(ch+1) + "/" + ofToString(cc);
                    ofRectangle bbox = verdana.getStringBoundingBox(text, 0, 0);
                    float x = fabs(r.getCenter().x - bbox.width / 2);
                    float y = fabs(r.getCenter().y + bbox.height / 2) - 2;
                    verdana.drawString(text, x, y);
                }
            }
        }
        
        ofPopStyle();
    }
}
示例#21
0
文件: plotter.cpp 项目: azorg/gqrx
/*! \brief Set upper limit of dB scale. */
void CPlotter::setMaxDB(float max)
{
    m_MaxdB = max;

    if (m_Running)
    {
        m_DrawOverlay = true;
    }
    else
        drawOverlay();

    m_PeakHoldValid = false;

}
示例#22
0
void Scene::onPaint()
{
    // Update data in the scene
	if ( !_frozen )
		updateScene();

    // Clear the screen
    glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );

    // Set camera parameters
    int width = glutGet( GLUT_WINDOW_WIDTH );
    int height = glutGet( GLUT_WINDOW_HEIGHT );
    glViewport( 0, 0, width, height );
    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    gluPerspective( 90, width/height, 1.0, 2048.0 );

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
	if (_freeCamera)
	{
		gluLookAt( _FCdist, 3.0, 0.0, _FCx, 0.0, _FCz, 0.0, 1.0, 0.0 );

		glRotatef( _rotationX, 0.0, 0.0, 1.0 );
	    glRotatef( _rotationY, 0.0, 1.0, 0.0 );
    }
	else
	{
		Point position = _playerTank.getPosition();
		Vector3D direction = _playerTank.getDirection();
		float offsetBack = 5.0f;
		float offsetUp = 3.0f;
		float eye[3] = { position.x - offsetBack * direction.x, position.y + offsetUp, position.z - offsetBack * direction.z };
		gluLookAt( eye[0], eye[1], eye[2], position.x, position.y, position.z, 0.0f, 1.0f, 0.0f );

		// set values for sound listener
		float ear[3] = { position.x, position.y, position.z };
		float orientation[6] = { position.x - eye[0], position.y - eye[1], position.z - eye[2], 0.0f, 1.0f, 0.0f };
		Sound::setListener(ear, orientation);
	}

    // Draw screen
	_landscape.draw(); //make sure _landscape.settimesincelastupdate(f) has been called first)
    //drawPlane();
    drawScene();

    drawOverlay();

    glutSwapBuffers();
}
示例#23
0
文件: plotter.cpp 项目: scottdm/gqrx
void CPlotter::setDemodRanges(int FLowCmin, int FLowCmax, int FHiCmin, int FHiCmax, bool symetric)
{
    m_FLowCmin=FLowCmin;
    m_FLowCmax=FLowCmax;
    m_FHiCmin=FHiCmin;
    m_FHiCmax=FHiCmax;
    m_symetric=symetric;
    clampDemodParameters();

    if (m_Running)
        m_DrawOverlay = true;
    else
        drawOverlay();
}
示例#24
0
void OscController::draw(ofEventArgs &args){
    if(bMapModeEnabled){
        ofPushStyle();
        ofSetLineWidth(2);
        
        // draw the rectangles on top of the controls
        ofEnableBlendMode(OF_BLENDMODE_ALPHA);
        for(auto it = controls.begin(); it != controls.end(); ++it){
            string controlName = it->first;
            ofxBaseGui* control = it->second;
            
            if(controlName == selected){
                drawOverlay(control, colorHighlight, ofColor(255));
            }else{
                drawOverlay(control, colorNormal, ofColor(0));
            }
        }
        ofDisableBlendMode();
        
        // draw the labels of the mapped addresses
        for (map<string,string>::iterator it=addressToName.begin(); it!=addressToName.end(); ++it){
            string controlName = it->second;
            ofxBaseGui* control = controls[controlName];
            ofRectangle r = control->getShape();
            ofSetColor(255);
            ofRectangle bbox = verdana14.getStringBoundingBox(it->first, 0, 0);
            float x = fabs(r.getCenter().x - bbox.width / 2);
            float y = fabs(r.getCenter().y + bbox.height / 2);
            verdana14.drawString(it->first, x, y);
        }
        
        // draw mismatch message
        //ofDrawBitmapStringHighlight(mismatchMessage, 10, 10, ofColor::darkRed);
        
        ofPopStyle();
    }
}
示例#25
0
	void redrawScreen()
	{
		screen.composite();
		drawOverlay();

		GLMeta::blitBeginScreen(winSize);
		GLMeta::blitSource(screen.getPP().frontBuffer());

		FBO::clear();
		metaBlitBufferFlippedScaled();

		GLMeta::blitEnd();

		swapGLBuffer();
	}
示例#26
0
void GUIEngine::run()
{
	// Always create clouds because they may or may not be
	// needed based on the game selected
	video::IVideoDriver* driver = m_device->getVideoDriver();

	cloudInit();

	unsigned int text_height = g_fontengine->getTextHeight();

	while(m_device->run() && (!m_startgame) && (!m_kill))
	{
		//check if we need to update the "upper left corner"-text
		if (text_height != g_fontengine->getTextHeight()) {
			updateTopLeftTextSize();
			text_height = g_fontengine->getTextHeight();
		}

		driver->beginScene(true, true, video::SColor(255,140,186,250));

		if (m_clouds_enabled)
		{
			cloudPreProcess();
			drawOverlay(driver);
		}
		else
			drawBackground(driver);

		drawHeader(driver);
		drawFooter(driver);

		m_device->getGUIEnvironment()->drawAll();

		driver->endScene();

		if (m_clouds_enabled)
			cloudPostProcess();
		else
			sleep_ms(25);

		m_script->step();

#ifdef __ANDROID__
		m_menu->getAndroidUIInput();
#endif
	}
}
void SurfaceSdlGraphicsManager::updateScreen() {
#ifdef USE_OPENGL
    if (_opengl) {
        if (_frameBuffer) {
            _frameBuffer->detach();
            glViewport(0, 0, _screen->w, _screen->h);
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
#ifndef USE_OPENGL_SHADERS
            drawFramebufferOpenGL();
#else
            drawFramebufferOpenGLShaders();
#endif
        }

        if (_overlayVisible) {
            if (_overlayDirty) {
                updateOverlayTextures();
            }

#ifndef USE_OPENGL_SHADERS
            drawOverlayOpenGL();
#else
            drawOverlayOpenGLShaders();
#endif
        }

        SDL_GL_SwapBuffers();

        if (_frameBuffer) {
            _frameBuffer->attach();
        }
    } else
#endif
    {
        SDL_Rect dstrect;
        dstrect.x = _gameRect.getTopLeft().getX();
        dstrect.y = _gameRect.getTopLeft().getY();
        dstrect.w = _gameRect.getWidth();
        dstrect.h = _gameRect.getHeight();
        SDL_BlitSurface(_subScreen, NULL, _screen, &dstrect);
        if (_overlayVisible) {
            drawOverlay();
        }
        SDL_Flip(_screen);
    }
}
示例#28
0
void Map::draw(Graphics *graphics, int scrollX, int scrollY)
{
    int endPixelY = graphics->getHeight() + scrollY + mTileHeight - 1;

    // TODO: Do this per-layer
    endPixelY += mMaxTileHeight - mTileHeight;

    int startX = scrollX / mTileWidth;
    int startY = scrollY / mTileHeight;
    int endX = (graphics->getWidth() + scrollX + mTileWidth - 1) / mTileWidth;
    int endY = endPixelY / mTileHeight;

    // Make sure sprites are sorted
    mSprites.sort(spriteCompare);

    // draw the game world
    Layers::const_iterator layeri = mLayers.begin();
    for (; layeri != mLayers.end(); ++layeri)
    {
        (*layeri)->draw(graphics,
                        startX, startY, endX, endY,
                        scrollX, scrollY,
                        mSprites);
    }

    // Draws beings with a lower opacity to make them visible
    // even when covered by a wall or some other elements...
    MapSprites::const_iterator si = mSprites.begin();
    while (si != mSprites.end())
    {
        if (Sprite *sprite = *si)
        {
            // For now, just draw sprites with only one layer.
            if (sprite->getNumberOfLayers() == 1)
            {
                sprite->setAlpha(0.3f);
                sprite->draw(graphics, -scrollX, -scrollY);
            }
        }
        si++;
    }

    drawOverlay(graphics, scrollX, scrollY,
            (int) config.getValue("OverlayDetail", 2));
}
示例#29
0
文件: view.cpp 项目: Windfisch/muse
void View::paint(const QRect& r)
      {
      #ifdef VIEW_USE_DOUBLE_BUFFERING
      if (pm.isNull())
            return;
      #endif
      
      QRect rr(r);
      
      //printf("View::paint x:%d width:%d y:%d height:%d\n", r.x(), r.width(), r.y(), r.height());   
      
      #ifdef VIEW_USE_DOUBLE_BUFFERING
      if (!pmValid) {
            pmValid = true;
            rr = QRect(0, 0, pm.width(), pm.height());
            }
      
      QPainter p(&pm);
      #else
      QPainter p(this);
      #endif
      
      p.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::HighQualityAntialiasing, false);
      
      if (bgPixmap.isNull())
            p.fillRect(rr, brush);
      else
            p.drawTiledPixmap(rr, bgPixmap, QPoint(xpos + rmapx(xorg)
               + rr.x(), ypos + rmapy(yorg) + rr.y()));
      
      p.setClipRegion(rr);

      //printf("View::paint r.x:%d w:%d\n", rr.x(), rr.width());
      pdraw(p, rr);       // draw into pixmap

      p.resetMatrix();      // Q3 support says use resetMatrix instead, but resetMatrix advises resetTransform instead...
      //p.resetTransform();
      
      drawOverlay(p);
      }
void SurfaceSdlGraphicsManager::updateScreen() {
#ifdef USE_OPENGL
	if (_opengl) {
		if (_overlayVisible) {
			if (_overlayDirty) {
				updateOverlayTextures();
			}

#ifndef USE_OPENGL_SHADERS
			drawOverlayOpenGL();
#else
			drawOverlayOpenGLShaders();
#endif
		}
		SDL_GL_SwapBuffers();
	} else
#endif
	{
		if (_overlayVisible) {
			drawOverlay();
		}
		SDL_Flip(_screen);
	}
}