text:
layout: post
authors: ["Belinda Weaver"]
title: "Why be a helper at Software Carpentry workshops?"
date: 2017-07-01
time: "06:00:00"
category: [ "Workshops", "Helpers"]
---

"I'm not an expert on R", "I don't know any Python", "I've never used Git" - these may be true statements but they should
never stop you from helping out at a Software Carpentry workshop.

Even the workshop instructors themselves may not be "experts" - and all the better if they are not!

Experts don't necessarily make the best teachers. Many have lost sight of - or, worse, patience with - the beginner mindset.

Software Carpentry's worldwide community of volunteer instructors include experts, near-learners and plenty of people in between.
What they share is a willingness to teach their peers. And that's all a helper really needs - the willingness to lend a hand.

It's fine to say you don't know the answer to something, or to call for help with a question that stumps you.
Let the instructors deal with anything knotty that crops up.

Most workshop hiccups are much simpler - a typo, issues with the wifi, or learners not being able to locate a downloaded file.
Learners might have fallen behind, in which case all they need to get caught up is to be shown the right spot in
the online lesson. Or perhaps they overlooked the etherpad link. These are all simple problems that you don't need to be
an expert to fix. Sometimes it's enough just to be familiar with a Mac or with Windows, so that people using
unfamiliar laptops can navigate their way around an operating system.

All kinds of help are welcome at Software Carpentry workshops. Perhaps you can paste challenges into the
etherpad. Collect sticky note feedback. Write links on a whiteboard. Point people to the best coffee or lunch place on campus.

It certainly helps if you've had time to review what will be taught. That way, you will be quicker to spot a typo
or locate the spot where the learner needs to find the lesson. But don't pretend to know more than you do.
Learners will appreciate your honesty.

The main thing is to be friendly and approachable.

Helping at a workshop is a way to see workshops in action. You may be trying to figure out if you'd like to become an instructor yourself. You might even want to have a crack at teaching a section, knowing there are more experienced instructors in the room should you run into problems. You can certainly learn a lot about instructing by watching others. Many helpers do go on to become instructors themselves, reinforcing their own learning by teaching the material to other people.

If you have attended a workshop before, helping may reinforce your own learning. Hearing things explained again can really help consolidate your knowledge. You might also pick up new tricks and tips. A key benefit is helping people get started,
feeling you are making a contribution to their learning, and to the learning community within your institution.
It might kickstart a new community of practice, or just a networking group for when times get tough
and you need to talk your work over with someone who is struggling with the same problems.

So what are you waiting for? FInd a workshop near you and volunteer. You will be made very welcome in what is a great, global community.


text:
/* -*-c++-*--------------------------------------------------------------------
 * 2017 Bernd Pfrommer bernd.pfrommer@gmail.com
 */

#ifndef BIRD_RECORDING_CALIBRATION_TESTER_H
#define BIRD_RECORDING_CALIBRATION_TESTER_H

#include "bird_recording/tag.h"
#include "bird_recording/image_sync.h"
#include "bird_recording/image_sync_listener.h"
#include "bird_recording/camera.h"

#include <ros/ros.h>
#include <sensor_msgs/Image.h>
#include <sensor_msgs/CameraInfo.h>
#include <opencv2/core/core.hpp>
#include <opencv2/core/affine.hpp>
#include <memory>

namespace bird_recording {
  using sensor_msgs::Image;
  using sensor_msgs::ImageConstPtr;

  class CalibrationTester : public ImageSyncListener {

  public:
    CalibrationTester(const ros::NodeHandle &pnh);
    ~CalibrationTester();

    CalibrationTester(const CalibrationTester&) = delete;
    CalibrationTester& operator=(const CalibrationTester&) = delete;

    bool initialize();
    void syncCallback(const ImageSync::ImgVecPtr &images) override;

  private:
    void    getCameraCalibrations();
    void    test(const ros::Time &stamp,
                 const std::vector<cv::Mat> &images,
                 const cv::Mat &grid) const;
    void  projectTags(const ros::Time &stamp,
                      const std::vector<cv::Mat> &images,
                      const cv::Mat &points) const;

    cv::Mat getTagCorners() const;

    ros::NodeHandle     nh_;
    ImageSync           imageSync_;
    std::vector<Camera> cameras_;
    std::vector<Tag>    tags_;
  };
}

#endif

redpajama_set_name: RedPajamaGithub


text:
feature("Initializing a Mask",function(){
	scenario("An input with no value",function(){
		given("an input with no value",function(){
			input.val("");
		});
		when("setting a mask with two placeholders",function(){
			input.mask("99");
		});
		then("the value should be an empty string",function(){
			expect(input).toHaveValue("");
		});
	});

	scenario("An input with a valid value and no placeholders remaining",function(){
		given("an input with a valid value",function(){
			input.val("5555555555");
		});
		when("setting a mask",function(){
			input.mask("(999) 999-9999");
		});
		then("the value should be intact",function(){
			expect(input).toHaveValue("(555) 555-5555");
		});
	});

	scenario("An input with a valid value ending in a literal",function(){
		given("an input with a valid value",function(){
			input.val("12");
		});
		when("setting a mask",function(){
			input.mask("(99)");
		});
		then("the value should be intact",function(){
			expect(input).toHaveValue("(12)");
		});
	});

	scenario("An input with an invalid value and placeholders remaining",function(){
		given("an invalid input value",function(){
			input.val("55555555");
		});
		when("setting a mask",function(){
			input.mask("(999) 999-9999");
		});
		then("the value should be empty",function(){
			expect(input).toHaveValue("");
		});
	});

	scenario("An input with an invalid value, placeholders remaining and autoclear set to false",function(){
		given("an invalid input value",function(){
			input.val("55555555");
		});
		when("setting a mask with autoclear set to false",function(){
			input.mask("(999) 999-9999", { autoclear: false });
		});
		then("the value be intact with placeholders visible",function(){
			expect(input).toHaveValue("(555) 555-55__");
		});
	});

	scenario("An input no value and autoclear set to false", function() {
		given("an input with no value",function(){
			input.val("");
		});
		when("setting a mask with autoclear set to false",function(){
			input.mask("(999) 999-9999", { autoclear: false });
		});
		then("the value should be empty",function(){
			expect(input).toHaveValue("");
		});
	});
});


text:
<?php

// if the url field is empty
if(isset($_POST['url']) && $_POST['url'] == ''){

	// then send the form to your email
	mail( 'hannibalandersen@gmail.com', 'Contact Form', print_r($_POST,true) );
}

// otherwise, let the spammer think that they got their message through

?>
<!DOCTYPE HTML>

<title>Thanks!</title>

Thanks

We'll get back to you as soon as possible.


text:
<?php
# Generated by the protocol buffer compiler.  DO NOT EDIT!
# source: google/cloud/ids/v1/ids.proto

namespace Google\Cloud\Ids\V1;

use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\RepeatedField;
use Google\Protobuf\Internal\GPBUtil;

/**
 * Generated from protobuf message google.cloud.ids.v1.ListEndpointsRequest
 */
class ListEndpointsRequest extends \Google\Protobuf\Internal\Message
{
    /**
     * Required. The parent, which owns this collection of endpoints.
     *
     * Generated from protobuf field string parent = 1 [(.google.api.field_behavior) = REQUIRED, (.google.api.resource_reference) = {
     */
    private $parent = '';
    /**
     * Optional. The maximum number of endpoints to return. The service may return fewer
     * than this value.
     *
     * Generated from protobuf field int32 page_size = 2 [(.google.api.field_behavior) = OPTIONAL];
     */
    private $page_size = 0;
    /**
     * Optional. A page token, received from a previous `ListEndpoints` call.
     * Provide this to retrieve the subsequent page.
     * When paginating, all other parameters provided to `ListEndpoints` must
     * match the call that provided the page token.
     *
     * Generated from protobuf field string page_token = 3 [(.google.api.field_behavior) = OPTIONAL];
     */
    private $page_token = '';
    /**
     * Optional. The filter expression, following the syntax outlined in
     * https://google.aip.dev/160.
     *
     * Generated from protobuf field string filter = 4 [(.google.api.field_behavior) = OPTIONAL];
     */
    private $filter = '';
    /**
     * Optional. One or more fields to compare and use to sort the output.
     * See https://google.aip.dev/132#ordering.
     *
     * Generated from protobuf field string order_by = 5 [(.google.api.field_behavior) = OPTIONAL];
     */
    private $order_by = '';

    /**
     * Constructor.
     *
     * @param array $data {
     *     Optional. Data for populating the Message object.
     *
     *     @type string $parent
     *           Required. The parent, which owns this collection of endpoints.
     *     @type int $page_size
     *           Optional. The maximum number of endpoints to return. The service may return fewer
     *           than this value.
     *     @type string $page_token
     *           Optional. A page token, received from a previous `ListEndpoints` call.
     *           Provide this to retrieve the subsequent page.
     *           When paginating, all other parameters provided to `ListEndpoints` must
     *           match the call that provided the page token.
     *     @type string $filter
     *           Optional. The filter expression, following the syntax outlined in
     *           https://google.aip.dev/160.
     *     @type string $order_by
     *           Optional. One or more fields to compare and use to sort the output.
     *           See https://google.aip.dev/132#ordering.
     * }
     */
    public function __construct($data = NULL) {
        \GPBMetadata\Google\Cloud\Ids\V1\Ids::initOnce();
        parent::__construct($data);
    }

    /**
     * Required. The parent, which owns this collection of endpoints.
     *
     * Generated from protobuf field string parent = 1 [(.google.api.field_behavior) = REQUIRED, (.google.api.resource_reference) = {
     * @return string
     */
    public function getParent()
    {
        return $this->parent;
    }

    /**
     * Required. The parent, which owns this collection of endpoints.
     *
     * Generated from protobuf field string parent = 1 [(.google.api.field_behavior) = REQUIRED, (.google.api.resource_reference) = {
     * @param string $var
     * @return $this
     */
    public function setParent($var)
    {
        GPBUtil::checkString($var, True);
        $this->parent = $var;

        return $this;
    }

    /**
     * Optional. The maximum number of endpoints to return. The service may return fewer
     * than this value.
     *
     * Generated from protobuf field int32 page_size = 2 [(.google.api.field_behavior) = OPTIONAL];
     * @return int
     */
    public function getPageSize()
    {
        return $this->page_size;
    }

    /**
     * Optional. The maximum number of endpoints to return. The service may return fewer
     * than this value.
     *
     * Generated from protobuf field int32 page_size = 2 [(.google.api.field_behavior) = OPTIONAL];
     * @param int $var
     * @return $this
     */
    public function setPageSize($var)
    {
        GPBUtil::checkInt32($var);
        $this->page_size = $var;

        return $this;
    }

    /**
     * Optional. A page token, received from a previous `ListEndpoints` call.
     * Provide this to retrieve the subsequent page.
     * When paginating, all other parameters provided to `ListEndpoints` must
     * match the call that provided the page token.
     *
     * Generated from protobuf field string page_token = 3 [(.google.api.field_behavior) = OPTIONAL];
     * @return string
     */
    public function getPageToken()
    {
        return $this->page_token;
    }

    /**
     * Optional. A page token, received from a previous `ListEndpoints` call.
     * Provide this to retrieve the subsequent page.
     * When paginating, all other parameters provided to `ListEndpoints` must
     * match the call that provided the page token.
     *
     * Generated from protobuf field string page_token = 3 [(.google.api.field_behavior) = OPTIONAL];
     * @param string $var
     * @return $this
     */
    public function setPageToken($var)
    {
        GPBUtil::checkString($var, True);
        $this->page_token = $var;

        return $this;
    }

    /**
     * Optional. The filter expression, following the syntax outlined in
     * https://google.aip.dev/160.
     *
     * Generated from protobuf field string filter = 4 [(.google.api.field_behavior) = OPTIONAL];
     * @return string
     */
    public function getFilter()
    {
        return $this->filter;
    }

    /**
     * Optional. The filter expression, following the syntax outlined in
     * https://google.aip.dev/160.
     *
     * Generated from protobuf field string filter = 4 [(.google.api.field_behavior) = OPTIONAL];
     * @param string $var
     * @return $this
     */
    public function setFilter($var)
    {
        GPBUtil::checkString($var, True);
        $this->filter = $var;

        return $this;
    }

    /**
     * Optional. One or more fields to compare and use to sort the output.
     * See https://google.aip.dev/132#ordering.
     *
     * Generated from protobuf field string order_by = 5 [(.google.api.field_behavior) = OPTIONAL];
     * @return string
     */
    public function getOrderBy()
    {
        return $this->order_by;
    }

    /**
     * Optional. One or more fields to compare and use to sort the output.
     * See https://google.aip.dev/132#ordering.
     *
     * Generated from protobuf field string order_by = 5 [(.google.api.field_behavior) = OPTIONAL];
     * @param string $var
     * @return $this
     */
    public function setOrderBy($var)
    {
        GPBUtil::checkString($var, True);
        $this->order_by = $var;

        return $this;
    }

}


text:
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
	<display-name>sql-web</display-name>
	<servlet>
		<description>
		</description>
		<display-name>SqlServlet</display-name>
		<servlet-name>SqlServlet</servlet-name>
		<servlet-class>sql.servlet.SqlServlet</servlet-class>
		<init-param>
			<param-name>sql-config</param-name>
			<param-value>jndi:java:comp/env/config/sqlconfig</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>SqlServlet</servlet-name>
		<url-pattern>/sql</url-pattern>
	</servlet-mapping>
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
		<welcome-file>index.htm</welcome-file>
		<welcome-file>index.jsp</welcome-file>
		<welcome-file>default.html</welcome-file>
		<welcome-file>default.htm</welcome-file>
		<welcome-file>default.jsp</welcome-file>
	</welcome-file-list>
	<jsp-config>
		<taglib>
			<taglib-uri>/morozko/mhtml</taglib-uri>
			<taglib-location>/WEB-INF/tlds/mhtml-1-0.tld</taglib-location>
		</taglib>
		<taglib>
			<taglib-uri>/morozko/mlogic</taglib-uri>
			<taglib-location>/WEB-INF/tlds/mlogic-1-0.tld</taglib-location>
		</taglib>
		<taglib>
			<taglib-uri>/morozko/mlist</taglib-uri>
			<taglib-location>/WEB-INF/tlds/mlist-1-0.tld</taglib-location>
		</taglib>
		<taglib>
			<taglib-uri>/morozko/mformat</taglib-uri>
			<taglib-location>/WEB-INF/tlds/mformat-1-0.tld</taglib-location>
		</taglib>
		<taglib>
			<taglib-uri>/morozko/mmap</taglib-uri>
			<taglib-location>/WEB-INF/tlds/mmap-1-0.tld</taglib-location>
		</taglib>
		<taglib>
			<taglib-uri>http://java.sun.com/jsp/jstl/core</taglib-uri>
			<taglib-location>/WEB-INF/tlds/c.tld</taglib-location>
		</taglib>
	</jsp-config>

	<security-role>
		<role-name>manager</role-name>
	</security-role>

	<security-constraint>
		<display-name>admin_users</display-name>
		<web-resource-collection>
			<web-resource-name>admin_users</web-resource-name>
			<url-pattern>/*</url-pattern>
			<http-method>GET</http-method>
			<http-method>PUT</http-method>
			<http-method>HEAD</http-method>
			<http-method>TRACE</http-method>
			<http-method>POST</http-method>
			<http-method>DELETE</http-method>
			<http-method>OPTIONS</http-method>
		</web-resource-collection>
		<auth-constraint>
			<description>admin_users</description>
			<role-name>manager</role-name>
		</auth-constraint>
	</security-constraint>

	<login-config>
		<auth-method>BASIC</auth-method>
	</login-config>

</web-app>


text:
class PizzaTopping < ActiveRecord::Base
  belongs_to :dish
  belongs_to :ingredient
end


text:
$payment = new Paymill\Models\Request\Payment();
$payment->setToken('12a46bcd462sd3r3care4e8336ssb4f5');

$response = $request->create($payment);


text:
package com.tom_roush.pdfbox.pdmodel.interactive.annotation;

import com.tom_roush.pdfbox.cos.COSArray;
import com.tom_roush.pdfbox.cos.COSBase;
import com.tom_roush.pdfbox.cos.COSDictionary;
import com.tom_roush.pdfbox.cos.COSFloat;
import com.tom_roush.pdfbox.cos.COSName;
import com.tom_roush.pdfbox.pdmodel.PDDocument;
import com.tom_roush.pdfbox.pdmodel.common.PDRectangle;
import com.tom_roush.pdfbox.pdmodel.graphics.color.PDColor;
import com.tom_roush.pdfbox.pdmodel.interactive.annotation.handlers.PDAppearanceHandler;
import com.tom_roush.pdfbox.pdmodel.interactive.annotation.handlers.PDCircleAppearanceHandler;
import com.tom_roush.pdfbox.pdmodel.interactive.annotation.handlers.PDSquareAppearanceHandler;

/**
 * This is the class that represents a rectangular or eliptical annotation Introduced in PDF 1.3 specification .
 *
 * @author Paul King
 */
public class PDAnnotationSquareCircle extends PDAnnotationMarkup
{

    /**
     * Constant for a Rectangular type of annotation.
     */
    public static final String SUB_TYPE_SQUARE = "Square";
    /**
     * Constant for an elliptical type of annotation.
     */
    public static final String SUB_TYPE_CIRCLE = "Circle";

    private PDAppearanceHandler customAppearanceHandler;

    /**
     * Creates a Circle or Square annotation of the specified sub type.
     *
     * @param subType the subtype the annotation represents.
     */
    public PDAnnotationSquareCircle(String subType)
    {
        setSubtype(subType);
    }

    /**
     * Creates a Line annotation from a COSDictionary, expected to be a correct object definition.
     *
     * @param field the PDF object to represent as a field.
     */
    public PDAnnotationSquareCircle(COSDictionary field)
    {
        super(field);
    }

    /**
     * This will set interior color of the drawn area color is in DeviceRGB colo rspace.
     *
     * @param ic color in the DeviceRGB color space.
     *
     */
    public void setInteriorColor(PDColor ic)
    {
        getCOSObject().setItem(COSName.IC, ic.toCOSArray());
    }

    /**
     * This will retrieve the interior color of the drawn area color is in DeviceRGB color space.
     *
     * @return object representing the color.
     */
    public PDColor getInteriorColor()
    {
        return getColor(COSName.IC);
    }

    /**
     * This will set the border effect dictionary, specifying effects to be applied when drawing the line.
     *
     * @param be The border effect dictionary to set.
     *
     */
    public void setBorderEffect(PDBorderEffectDictionary be)
    {
        getCOSObject().setItem(COSName.BE, be);
    }

    /**
     * This will retrieve the border effect dictionary, specifying effects to be applied used in drawing the line.
     *
     * @return The border effect dictionary
     */
    public PDBorderEffectDictionary getBorderEffect()
    {
        COSDictionary be = (COSDictionary) getCOSObject().getDictionaryObject(COSName.BE);
        if (be != null)
        {
            return new PDBorderEffectDictionary(be);
        }
        else
        {
            return null;
        }
    }

    /**
     * This will set the rectangle difference rectangle. Giving the difference between the annotations rectangle and
     * where the drawing occurs. (To take account of any effects applied through the BE entry forexample)
     *
     * @param rd the rectangle difference
     *
     */
    public void setRectDifference(PDRectangle rd)
    {
        getCOSObject().setItem(COSName.RD, rd);
    }

    /**
     * This will get the rectangle difference rectangle. Giving the difference between the annotations rectangle and
     * where the drawing occurs. (To take account of any effects applied through the BE entry forexample)
     *
     * @return the rectangle difference
     */
    public PDRectangle getRectDifference()
    {
        COSArray rd = (COSArray) getCOSObject().getDictionaryObject(COSName.RD);
        if (rd != null)
        {
            return new PDRectangle(rd);
        }
        else
        {
            return null;
        }
    }

    /**
     * This will set the sub type (and hence appearance, AP taking precedence) For this annotation. See the SUB_TYPE_XXX
     * constants for valid values.
     *
     * @param subType The subtype of the annotation
     */
    public void setSubtype(String subType)
    {
        getCOSObject().setName(COSName.SUBTYPE, subType);
    }

    /**
     * This will retrieve the sub type (and hence appearance, AP taking precedence) For this annotation.
     *
     * @return The subtype of this annotation, see the SUB_TYPE_XXX constants.
     */
    @Override
    public String getSubtype()
    {
        return getCOSObject().getNameAsString(COSName.SUBTYPE);
    }

    /**
     * This will set the border style dictionary, specifying the width and dash pattern used in drawing the line.
     *
     * @param bs the border style dictionary to set. TODO not all annotations may have a BS entry
     *
     */
    @Override
    public void setBorderStyle(PDBorderStyleDictionary bs)
    {
        this.getCOSObject().setItem(COSName.BS, bs);
    }

    /**
     * This will retrieve the border style dictionary, specifying the width and dash pattern used in drawing the line.
     *
     * @return the border style dictionary. TODO not all annotations may have a BS entry
     */
    @Override
    public PDBorderStyleDictionary getBorderStyle()
    {
        COSBase bs = getCOSObject().getDictionaryObject(COSName.BS);
        if (bs instanceof COSDictionary)
        {
            return new PDBorderStyleDictionary((COSDictionary) bs);
        }
        return null;
    }

    /**
     * This will set the difference between the annotations "outer" rectangle defined by /Rect and
     * the border.
     *
     *

     * This will set an equal difference for all sides

     *
     * @param difference from the annotations /Rect entry
     */
    public void setRectDifferences(float difference)
    {
        setRectDifferences(difference, difference, difference, difference);
    }

    /**
     * This will set the difference between the annotations "outer" rectangle defined by
     * /Rect and the border.
     *
     * @param differenceLeft left difference from the annotations /Rect entry
     * @param differenceTop top difference from the annotations /Rect entry
     * @param differenceRight right difference from  the annotations /Rect entry
     * @param differenceBottom bottom difference from the annotations /Rect entry
     *
     */
    public void setRectDifferences(float differenceLeft, float differenceTop, float differenceRight, float differenceBottom)
    {
        COSArray margins = new COSArray();
        margins.add(new COSFloat(differenceLeft));
        margins.add(new COSFloat(differenceTop));
        margins.add(new COSFloat(differenceRight));
        margins.add(new COSFloat(differenceBottom));
        getCOSObject().setItem(COSName.RD, margins);
    }

    /**
     * This will get the differences between the annotations "outer" rectangle defined by
     * /Rect and the border.
     *
     * @return the differences. If the entry hasn't been set am empty array is returned.
     */
    public float[] getRectDifferences()
    {
        COSBase margin = getCOSObject().getItem(COSName.RD);
        if (margin instanceof COSArray)
        {
            return ((COSArray) margin).toFloatArray();
        }
        return new float[]{};
    }

    /**
     * Set a custom appearance handler for generating the annotations appearance streams.
     *
     * @param appearanceHandler
     */
    @Override
    public void setCustomAppearanceHandler(PDAppearanceHandler appearanceHandler)
    {
        customAppearanceHandler = appearanceHandler;
    }

    @Override
    public void constructAppearances()
    {
        this.constructAppearances(null);
    }

    @Override
    public void constructAppearances(PDDocument document)
    {
        if (customAppearanceHandler == null)
        {
            if (SUB_TYPE_CIRCLE.equals(getSubtype()))
            {
                PDCircleAppearanceHandler appearanceHandler = new PDCircleAppearanceHandler(this, document);
                appearanceHandler.generateAppearanceStreams();
            }
            else if (SUB_TYPE_SQUARE.equals(getSubtype()))
            {
                PDSquareAppearanceHandler appearanceHandler = new PDSquareAppearanceHandler(this, document);
                appearanceHandler.generateAppearanceStreams();
            }
        }
        else
        {
            customAppearanceHandler.generateAppearanceStreams();
        }
    }

}


text: An (in-progress) implementation of an object oriented mdp (Diuk et al., 2008)


text:
import { Operator } from '../Operator';
import { Observable } from '../Observable';
import { Subscriber } from '../Subscriber';
import { OuterSubscriber } from '../OuterSubscriber';
import { InnerSubscriber } from '../InnerSubscriber';
import { subscribeToResult } from '../util/subscribeToResult';

import { MonoTypeOperatorFunction, TeardownLogic } from '../types';

/**
 * Emits the most recently emitted value from the source Observable whenever
 * another Observable, the `notifier`, emits.
 *
 * It's like {@link sampleTime}, but samples whenever
 * the `notifier` Observable emits something.
 *
 * ![](sample.png)
 *
 * Whenever the `notifier` Observable emits a value or completes, `sample`
 * looks at the source Observable and emits whichever value it has most recently
 * emitted since the previous sampling, unless the source has not emitted
 * anything since the previous sampling. The `notifier` is subscribed to as soon
 * as the output Observable is subscribed.
 *
 * ## Example
 * On every click, sample the most recent "seconds" timer
 * ```javascript
 * import { fromEvent, interval } from 'rxjs';
 * import { sample } from 'rxjs/operators';
 *
 * const seconds = interval(1000);
 * const clicks = fromEvent(document, 'click');
 * const result = seconds.pipe(sample(clicks));
 * result.subscribe(x => console.log(x));
 * ```
 *
 * @see {@link audit}
 * @see {@link debounce}
 * @see {@link sampleTime}
 * @see {@link throttle}
 *
 * @param {Observable<any>} notifier The Observable to use for sampling the
 * source Observable.
 * @return {Observable<T>} An Observable that emits the results of sampling the
 * values emitted by the source Observable whenever the notifier Observable
 * emits value or completes.
 * @method sample
 * @owner Observable
 */
export function sample<T>(notifier: Observable<any>): MonoTypeOperatorFunction<T> {
  return (source: Observable<T>) => source.lift(new SampleOperator(notifier));
}

class SampleOperator<T> implements Operator<T, T> {
  constructor(private notifier: Observable<any>) {
  }

  call(subscriber: Subscriber<T>, source: any): TeardownLogic {
    const sampleSubscriber = new SampleSubscriber(subscriber);
    const subscription = source.subscribe(sampleSubscriber);
    subscription.add(subscribeToResult(sampleSubscriber, this.notifier));
    return subscription;
  }
}

/**
 * We need this JSDoc comment for affecting ESDoc.
 * @ignore
 * @extends {Ignored}
 */
class SampleSubscriber<T, R> extends OuterSubscriber<T, R> {
  private value: T;
  private hasValue: boolean = false;

  protected _next(value: T) {
    this.value = value;
    this.hasValue = true;
  }

  notifyNext(outerValue: T, innerValue: R,
             outerIndex: number, innerIndex: number,
             innerSub: InnerSubscriber<T, R>): void {
    this.emitValue();
  }

  notifyComplete(): void {
    this.emitValue();
  }

  emitValue() {
    if (this.hasValue) {
      this.hasValue = false;
      this.destination.next(this.value);
    }
  }
}


text:
#import "EMTagCommand.h"

NS_ASSUME_NONNULL_BEGIN

@implementation EMTagCommand

- (NSArray<EMErrorParameter *> *)validate {
    NSMutableArray<EMErrorParameter *> *ret =
    [NSMutableArray<EMErrorParameter *> array];
    if ([self.value length] == 0) {
        [ret addObject:[self emptyStringEMErr:@"tag" field:@"tag"]];
    }
    return ret;
}

@end

NS_ASSUME_NONNULL_END