text:
package stats

import (
	"time"

	"github.com/pion/interceptor"
	"github.com/pion/interceptor/internal/ntp"
	"github.com/pion/interceptor/internal/sequencenumber"
	"github.com/pion/logging"
	"github.com/pion/rtcp"
	"github.com/pion/rtp"
)

// Stats contains all the available statistics of RTP streams
type Stats struct {
	InboundRTPStreamStats
	OutboundRTPStreamStats
	RemoteInboundRTPStreamStats
	RemoteOutboundRTPStreamStats
}

type internalStats struct {
	inboundSequencerNumber           sequencenumber.Unwrapper
	inboundSequenceNumberInitialized bool
	inboundFirstSequenceNumber       int64
	inboundHighestSequenceNumber     int64

	inboundLastArrivalInitialized bool
	inboundLastArrival            time.Time
	inboundLastTransit            int

	remoteInboundFirstSequenceNumberInitialized bool
	remoteInboundFirstSequenceNumber            int64

	lastSenderReports []uint64

	lastReceiverReferenceTimes []uint64

	InboundRTPStreamStats
	OutboundRTPStreamStats

	RemoteInboundRTPStreamStats
	RemoteOutboundRTPStreamStats
}

type incomingRTP struct {
	ts         time.Time
	header     rtp.Header
	payloadLen int
	attr       interceptor.Attributes
}

type incomingRTCP struct {
	ts   time.Time
	pkts []rtcp.Packet
	attr interceptor.Attributes
}

type outgoingRTP struct {
	ts         time.Time
	header     rtp.Header
	payloadLen int
	attr       interceptor.Attributes
}

type outgoingRTCP struct {
	ts   time.Time
	pkts []rtcp.Packet
	attr interceptor.Attributes
}

type recorder struct {
	logger logging.LeveledLogger

	ssrc      uint32
	clockRate float64

	maxLastSenderReports          int
	maxLastReceiverReferenceTimes int

	incomingRTPChan  chan *incomingRTP
	incomingRTCPChan chan *incomingRTCP
	outgoingRTPChan  chan *outgoingRTP
	outgoingRTCPChan chan *outgoingRTCP
	getStatsChan     chan Stats
	done             chan struct{}
}

func newRecorder(ssrc uint32, clockRate float64) *recorder {
	return &recorder{
		logger:                        logging.NewDefaultLoggerFactory().NewLogger("stats_recorder"),
		ssrc:                          ssrc,
		clockRate:                     clockRate,
		maxLastSenderReports:          5,
		maxLastReceiverReferenceTimes: 5,
		incomingRTPChan:               make(chan *incomingRTP),
		incomingRTCPChan:              make(chan *incomingRTCP),
		outgoingRTPChan:               make(chan *outgoingRTP),
		outgoingRTCPChan:              make(chan *outgoingRTCP),
		getStatsChan:                  make(chan Stats),
		done:                          make(chan struct{}),
	}
}

func (r *recorder) Stop() {
	close(r.done)
}

func (r *recorder) GetStats() Stats {
	return <-r.getStatsChan
}

func (r *recorder) recordIncomingRTP(latestStats internalStats, v *incomingRTP) internalStats {
	sequenceNumber := latestStats.inboundSequencerNumber.Unwrap(v.header.SequenceNumber)
	if !latestStats.inboundSequenceNumberInitialized {
		latestStats.inboundFirstSequenceNumber = sequenceNumber
		latestStats.inboundSequenceNumberInitialized = true
	}
	if sequenceNumber > latestStats.inboundHighestSequenceNumber {
		latestStats.inboundHighestSequenceNumber = sequenceNumber
	}

	latestStats.InboundRTPStreamStats.PacketsReceived++
	expectedPackets := latestStats.inboundHighestSequenceNumber - latestStats.inboundFirstSequenceNumber + 1
	latestStats.InboundRTPStreamStats.PacketsLost = expectedPackets - int64(latestStats.InboundRTPStreamStats.PacketsReceived)

	if !latestStats.inboundLastArrivalInitialized {
		latestStats.inboundLastArrival = v.ts
		latestStats.inboundLastArrivalInitialized = true
	} else {
		arrival := int(v.ts.Sub(latestStats.inboundLastArrival).Seconds() * r.clockRate)
		transit := arrival - int(v.header.Timestamp)
		d := transit - latestStats.inboundLastTransit
		latestStats.inboundLastTransit = transit
		if d < 0 {
			d = -d
		}
		latestStats.InboundRTPStreamStats.Jitter += (1.0 / 16.0) * (float64(d) - latestStats.InboundRTPStreamStats.Jitter)
		latestStats.inboundLastArrival = v.ts
	}

	latestStats.LastPacketReceivedTimestamp = v.ts
	latestStats.HeaderBytesReceived += uint64(v.header.MarshalSize())
	latestStats.BytesReceived += uint64(v.header.MarshalSize() + v.payloadLen)
	return latestStats
}

func (r *recorder) recordOutgoingRTCP(latestStats internalStats, v *outgoingRTCP) internalStats {
	for _, pkt := range v.pkts {
		switch rtcpPkt := pkt.(type) {
		case *rtcp.FullIntraRequest:
			latestStats.InboundRTPStreamStats.FIRCount++
		case *rtcp.PictureLossIndication:
			latestStats.InboundRTPStreamStats.PLICount++
		case *rtcp.TransportLayerNack:
			latestStats.InboundRTPStreamStats.NACKCount++
		case *rtcp.SenderReport:
			latestStats.lastSenderReports = append(latestStats.lastSenderReports, rtcpPkt.NTPTime)
			if len(latestStats.lastSenderReports) > r.maxLastSenderReports {
				latestStats.lastSenderReports = latestStats.lastSenderReports[len(latestStats.lastSenderReports)-r.maxLastSenderReports:]
			}
		case *rtcp.ExtendedReport:
			for _, block := range rtcpPkt.Reports {
				if xr, ok := block.(*rtcp.ReceiverReferenceTimeReportBlock); ok {
					latestStats.lastReceiverReferenceTimes = append(latestStats.lastReceiverReferenceTimes, xr.NTPTimestamp)
					if len(latestStats.lastReceiverReferenceTimes) > r.maxLastReceiverReferenceTimes {
						latestStats.lastReceiverReferenceTimes = latestStats.lastReceiverReferenceTimes[len(latestStats.lastReceiverReferenceTimes)-r.maxLastReceiverReferenceTimes:]
					}
				}
			}
		}
	}
	return latestStats
}

func (r *recorder) recordOutgoingRTP(latestStats internalStats, v *outgoingRTP) internalStats {
	headerSize := v.header.MarshalSize()
	latestStats.OutboundRTPStreamStats.PacketsSent++
	latestStats.OutboundRTPStreamStats.BytesSent += uint64(headerSize + v.payloadLen)
	latestStats.HeaderBytesSent += uint64(headerSize)
	if !latestStats.remoteInboundFirstSequenceNumberInitialized {
		latestStats.remoteInboundFirstSequenceNumber = int64(v.header.SequenceNumber)
		latestStats.remoteInboundFirstSequenceNumberInitialized = true
	}
	return latestStats
}

func (r *recorder) recordIncomingRR(latestStats internalStats, pkt *rtcp.ReceiverReport, ts time.Time) internalStats {
	for _, report := range pkt.Reports {
		if report.SSRC == r.ssrc {
			if latestStats.remoteInboundFirstSequenceNumberInitialized {
				cycles := uint64(report.LastSequenceNumber & 0xFFFF0000)
				nr := uint64(report.LastSequenceNumber & 0x0000FFFF)
				highest := cycles*0xFFFF + nr
				latestStats.RemoteInboundRTPStreamStats.PacketsReceived = highest - uint64(report.TotalLost) - uint64(latestStats.remoteInboundFirstSequenceNumber) + 1
			}
			latestStats.RemoteInboundRTPStreamStats.PacketsLost = int64(report.TotalLost)
			latestStats.RemoteInboundRTPStreamStats.Jitter = float64(report.Jitter) / r.clockRate

			if report.Delay != 0 && report.LastSenderReport != 0 {
				for i := min(r.maxLastSenderReports, len(latestStats.lastSenderReports)) - 1; i >= 0; i-- {
					lastReport := latestStats.lastSenderReports[i]
					if (lastReport&0x0000FFFFFFFF0000)>>16 == uint64(report.LastSenderReport) {
						dlsr := time.Duration(float64(report.Delay) / 65536.0 * float64(time.Second))
						latestStats.RemoteInboundRTPStreamStats.RoundTripTime = (ts.Add(-dlsr)).Sub(ntp.ToTime(lastReport))
						latestStats.RemoteInboundRTPStreamStats.TotalRoundTripTime += latestStats.RemoteInboundRTPStreamStats.RoundTripTime
						latestStats.RemoteInboundRTPStreamStats.RoundTripTimeMeasurements++
						break
					}
				}
			}
			latestStats.FractionLost = float64(report.FractionLost) / 256.0
		}
	}
	return latestStats
}

func (r *recorder) recordIncomingXR(latestStats internalStats, pkt *rtcp.ExtendedReport, ts time.Time) internalStats {
	for _, report := range pkt.Reports {
		if xr, ok := report.(*rtcp.DLRRReportBlock); ok {
			for _, xrReport := range xr.Reports {
				if xrReport.LastRR != 0 && xrReport.DLRR != 0 {
					for i := min(r.maxLastReceiverReferenceTimes, len(latestStats.lastReceiverReferenceTimes)) - 1; i >= 0; i-- {
						lastRR := latestStats.lastReceiverReferenceTimes[i]
						if (lastRR&0x0000FFFFFFFF0000)>>16 == uint64(xrReport.LastRR) {
							dlrr := time.Duration(xrReport.DLRR/65536.0) * time.Second
							latestStats.RemoteOutboundRTPStreamStats.RoundTripTime = (ts.Add(-dlrr)).Sub(ntp.ToTime(lastRR))
							latestStats.RemoteOutboundRTPStreamStats.TotalRoundTripTime += latestStats.RemoteOutboundRTPStreamStats.RoundTripTime
							latestStats.RemoteOutboundRTPStreamStats.RoundTripTimeMeasurements++
						}
					}
				}
			}
		}
	}
	return latestStats
}

func (r *recorder) recordIncomingRTCP(latestStats internalStats, v *incomingRTCP) internalStats {
	for _, pkt := range v.pkts {
		switch pkt := pkt.(type) {
		case *rtcp.TransportLayerNack:
			latestStats.OutboundRTPStreamStats.NACKCount++
		case *rtcp.FullIntraRequest:
			latestStats.OutboundRTPStreamStats.FIRCount++
		case *rtcp.PictureLossIndication:
			latestStats.OutboundRTPStreamStats.PLICount++
		case *rtcp.ReceiverReport:
			return r.recordIncomingRR(latestStats, pkt, v.ts)
		case *rtcp.SenderReport:
			latestStats.RemoteOutboundRTPStreamStats.PacketsSent = uint64(pkt.PacketCount)
			latestStats.RemoteOutboundRTPStreamStats.BytesSent = uint64(pkt.OctetCount)
			latestStats.RemoteTimeStamp = ntp.ToTime(pkt.NTPTime)
			latestStats.ReportsSent++

		case *rtcp.ExtendedReport:
			return r.recordIncomingXR(latestStats, pkt, v.ts)
		}
	}
	return latestStats
}

func (r *recorder) Start() {
	latestStats := &internalStats{}
	for {
		select {
		case <-r.done:
			return
		case v := <-r.incomingRTPChan:
			s := r.recordIncomingRTP(*latestStats, v)
			latestStats = &s

		case v := <-r.outgoingRTCPChan:
			s := r.recordOutgoingRTCP(*latestStats, v)
			latestStats = &s

		case v := <-r.outgoingRTPChan:
			s := r.recordOutgoingRTP(*latestStats, v)
			latestStats = &s

		case v := <-r.incomingRTCPChan:
			s := r.recordIncomingRTCP(*latestStats, v)
			latestStats = &s

		case r.getStatsChan <- Stats{
			InboundRTPStreamStats:        latestStats.InboundRTPStreamStats,
			OutboundRTPStreamStats:       latestStats.OutboundRTPStreamStats,
			RemoteInboundRTPStreamStats:  latestStats.RemoteInboundRTPStreamStats,
			RemoteOutboundRTPStreamStats: latestStats.RemoteOutboundRTPStreamStats,
		}:
		}
	}
}

func (r *recorder) QueueIncomingRTP(ts time.Time, buf []byte, attr interceptor.Attributes) {
	if attr == nil {
		attr = make(interceptor.Attributes)
	}
	header, err := attr.GetRTPHeader(buf)
	if err != nil {
		r.logger.Warnf("failed to get RTP Header, skipping incoming RTP packet in stats calculation: %v", err)
		return
	}
	hdr := header.Clone()
	r.incomingRTPChan <- &incomingRTP{
		ts:         ts,
		header:     hdr,
		payloadLen: len(buf) - hdr.MarshalSize(),
		attr:       attr,
	}
}

func (r *recorder) QueueIncomingRTCP(ts time.Time, buf []byte, attr interceptor.Attributes) {
	if attr == nil {
		attr = make(interceptor.Attributes)
	}
	pkts, err := attr.GetRTCPPackets(buf)
	if err != nil {
		r.logger.Warnf("failed to get RTCP packets, skipping incoming RTCP packet in stats calculation: %v", err)
		return
	}
	r.incomingRTCPChan <- &incomingRTCP{
		ts:   ts,
		pkts: pkts,
		attr: attr,
	}
}

func (r *recorder) QueueOutgoingRTP(ts time.Time, header *rtp.Header, payload []byte, attr interceptor.Attributes) {
	hdr := header.Clone()
	r.outgoingRTPChan <- &outgoingRTP{
		ts:         ts,
		header:     hdr,
		payloadLen: len(payload),
		attr:       attr,
	}
}

func (r *recorder) QueueOutgoingRTCP(ts time.Time, pkts []rtcp.Packet, attr interceptor.Attributes) {
	r.outgoingRTCPChan <- &outgoingRTCP{
		ts:   ts,
		pkts: pkts,
		attr: attr,
	}
}

func min(a, b int) int {
	if a < b {
		return a
	}
	return b
}


text:
<?php

// No direct access
defined('_HZEXEC_') or die();

if (Pathway::count() <= 0)
{
	Pathway::append(
		Lang::txt(strtoupper($this->option)),
		'index.php?option=' . $this->option
	);
}

Document::setTitle(Lang::txt('COM_ANSWERS'));

$this->css()
     ->js();

if (!$this->filters['filterby'] || $this->filters['filterby'] == 'none')
{
	$this->filters['filterby'] = 'all';
}
$sortdir = $this->filters['sort_Dir'] == 'DESC' ? 'ASC' : 'DESC';
?>

<?php echo Lang::txt('COM_ANSWERS'); ?>

	<?php if (User::authorise('core.create', $this->option)) { ?>

			<a class="icon-add add btn" href="<?php echo Route::url('index.php?option=' . $this->option . '&task=new'); ?>">
				<?php echo Lang::txt('COM_ANSWERS_NEW_QUESTION'); ?>

	<?php } ?>

			<form method="get" action="<?php echo Route::url('index.php?option=' . $this->option); ?>">

					<input class="entry-search-submit" type="submit" value="<?php echo Lang::txt('COM_ANSWERS_SEARCH'); ?>" />
					<fieldset class="entry-search">
						<legend><?php echo Lang::txt('COM_ANSWERS_SEARCH'); ?></legend>
						<?php echo Lang::txt('COM_ANSWERS_SEARCH_LABEL'); ?>
						<input type="text" name="q" id="entry-search-field" value="<?php echo $this->escape($this->filters['search']); ?>" placeholder="<?php echo Lang::txt('COM_ANSWERS_SEARCH_PLACEHOLDER'); ?>" />
						<input type="hidden" name="option" value="<?php echo $this->option; ?>" />
						<input type="hidden" name="area" value="<?php echo $this->escape($this->filters['area']); ?>" />
						<input type="hidden" name="sortby" value="<?php echo $this->escape($this->filters['sortby']); ?>" />
						<input type="hidden" name="sortdir" value="<?php echo $this->escape($this->filters['sort_Dir']); ?>" />
						<input type="hidden" name="filterby" value="<?php echo $this->escape($this->filters['filterby']); ?>" />
						<input type="hidden" name="task" value="<?php echo $this->escape($this->task); ?>" />
					</fieldset>

					<?php if (!User::isGuest()) { ?>

									<a<?php echo ($this->filters['area'] == '') ? ' class="active"' : ''; ?> href="<?php echo Route::url('index.php?option=' . $this->option . '&task=search&filterby=' . urlencode($this->filters['filterby']).'&sortby=' . urlencode($this->filters['sortby'])); ?>">
										<?php echo Lang::txt('COM_ANSWERS_FILTER_EVERYTHING'); ?>

									<a<?php echo ($this->filters['area'] == 'mine') ? ' class="active"' : ''; ?> href="<?php echo Route::url('index.php?option=' . $this->option . '&task=search&area=mine&filterby=' . urlencode($this->filters['filterby']).'&sortby=' . urlencode($this->filters['sortby'])); ?>">
										<?php echo Lang::txt('COM_ANSWERS_QUESTIONS_I_ASKED'); ?>

									<a<?php echo ($this->filters['area'] == 'assigned') ? ' class="active"' : ''; ?> href="<?php echo Route::url('index.php?option=' . $this->option . '&task=search&area=assigned&filterby=' . urlencode($this->filters['filterby']).'&sortby=' . urlencode($this->filters['sortby'])); ?>">
										<?php echo Lang::txt('COM_ANSWERS_QUESTIONS_RELATED_TO_CONTRIBUTIONS'); ?>

								<?php
								foreach (Event::trigger('answers.onQuestionsFilters') as $opt)
								{
									if (empty($opt))
									{
										continue;
									}
									?>

										<a<?php echo ($this->filters['area'] == $opt['value']) ? ' class="active"' : ''; ?> href="<?php echo Route::url('index.php?option=' . $this->option . '&task=search&area=' . $opt['value'] . '&filterby=' . urlencode($this->filters['filterby']).'&sortby=' . urlencode($this->filters['sortby'])); ?>">
											<?php echo $opt['label']; ?>

									<?php
								}
								?>

					<?php } ?>

						<ul class="entries-menu order-options" data-label="<?php echo Lang::txt('COM_ANSWERS_SORT'); ?>">
						<?php if ($this->config->get('banking')) { ?>

								<a<?php echo ($this->filters['sortby'] == 'rewards') ? ' class="active"' : ''; ?> href="<?php echo Route::url('index.php?option=' . $this->option . '&task=search&area=' . urlencode($this->filters['area']).'&filterby=' . urlencode($this->filters['filterby']).'&sortby=rewards&sortdir=' . $sortdir); ?>" title="<?php echo Lang::txt('COM_ANSWERS_SORT_REWARDS_TITLE'); ?>">
									<?php echo Lang::txt('COM_ANSWERS_SORT_REWARDS'); ?>

						<?php } ?>

								<a<?php echo ($this->filters['sortby'] == 'votes') ? ' class="active"' : ''; ?> href="<?php echo Route::url('index.php?option=' . $this->option . '&task=search&area=' . urlencode($this->filters['area']).'&filterby=' . urlencode($this->filters['filterby']).'&sortby=votes&sortdir=' . $sortdir); ?>" title="<?php echo Lang::txt('COM_ANSWERS_SORT_POPULAR_TITLE'); ?>">
									<?php echo Lang::txt('COM_ANSWERS_SORT_POPULAR'); ?>

								<a<?php echo ($this->filters['sortby'] == 'date') ? ' class="active"' : ''; ?> href="<?php echo Route::url('index.php?option=' . $this->option . '&task=search&area=' . urlencode($this->filters['area']).'&filterby=' . urlencode($this->filters['filterby']).'&sortby=date&sortdir=' . $sortdir); ?>" title="<?php echo Lang::txt('COM_ANSWERS_SORT_RECENT_TITLE'); ?>">
									<?php echo Lang::txt('COM_ANSWERS_SORT_RECENT'); ?>

						<ul class="entries-menu filter-options" data-label="<?php echo Lang::txt('COM_ANSWERS_FILTER'); ?>">

								<a<?php echo ($this->filters['filterby'] == 'all' || $this->filters['filterby'] == '') ? ' class="active"' : ''; ?> href="<?php echo Route::url('index.php?option=' . $this->option . '&task=search&area=' . urlencode($this->filters['area']).'&filterby=all&sortby=' . urlencode($this->filters['sortby'])); ?>" title="<?php echo Lang::txt('COM_ANSWERS_FILTER_ALL_TITLE'); ?>">
									<?php echo Lang::txt('COM_ANSWERS_FILTER_ALL'); ?>

								<a<?php echo ($this->filters['filterby'] == 'open') ? ' class="active"' : ''; ?> href="<?php echo Route::url('index.php?option=' . $this->option . '&task=search&area=' . urlencode($this->filters['area']).'&filterby=open&sortby=' . urlencode($this->filters['sortby'])); ?>" title="<?php echo Lang::txt('COM_ANSWERS_FILTER_OPEN_TITLE'); ?>">
									<?php echo Lang::txt('COM_ANSWERS_FILTER_OPEN'); ?>

								<a<?php echo ($this->filters['filterby'] == 'closed') ? ' class="active"' : ''; ?> href="<?php echo Route::url('index.php?option=' . $this->option . '&task=search&area=' . urlencode($this->filters['area']).'&filterby=closed&sortby=' . urlencode($this->filters['sortby'])); ?>" title="<?php echo Lang::txt('COM_ANSWERS_FILTER_CLOSED_TITLE'); ?>">
									<?php echo Lang::txt('COM_ANSWERS_FILTER_CLOSED'); ?>

							<?php
								$total = $this->results->count();
								$s = ($total > 0) ? $this->filters['start']+1 : $this->filters['start'];
								$e = ($total > ($this->filters['start'] + $this->filters['limit'])) ? ($this->filters['start'] + $this->filters['limit']) : $total;
								if ($this->filters['search'] != '')
								{
									echo Lang::txt('COM_ANSWERS_SEARCH_FOR', $this->escape($this->filters['search']), Lang::txt('COM_ANSWERS_FILTER_' . strtoupper($this->filters['filterby'])));
								}
								else
								{
									echo Lang::txt('COM_ANSWERS_FILTER_' . strtoupper($this->filters['filterby']));
								}
							?>
							(<?php echo Lang::txt('COM_ANSWERS_RESULTS_TOTAL', $s, $e, $total); ?>)

				<?php if ($total > 0) { ?>
					<?php
					foreach ($this->results as $row)
					{
						// author name
						$name = Lang::txt('JANONYMOUS');
						if (!$row->get('anonymous'))
						{
							$name = $this->escape(stripslashes($row->creator->get('name', $name)));
							if (in_array($row->creator->get('access'), User::getAuthorisedViewLevels()) && !$row->creator->get('block') && $row->creator->get('approved'))
							{
								$name = 'creator->link()) . '">' . $name . '';
							}
						}
						$cls = ($row->isclosed())   ? 'answered' : '';
						$cls = ($row->isReported()) ? 'flagged' : $cls;
						$cls .= ($row->get('created_by') == User::get('id') ? ' mine' : '');

						$icn = ($row->isclosed())   ? 'icon-comments' : 'icon-comment-alt';
						$icn = ($row->isReported()) ? 'icon-flag' : $icn;
						?>
							<tr<?php if ($cls) { echo ' class="' . $cls . '"'; } ?>>

									<span class="entry-identifier <?php echo $icn; ?>"><?php echo $row->get('id'); ?>

									<?php if (!$row->isReported()) { ?>
										<a class="entry-title" href="<?php echo Route::url($row->link()); ?>">
											<?php echo $this->escape(strip_tags($row->get('subject'))); ?>

									<?php } else { ?>

											<?php echo Lang::txt('COM_ANSWERS_QUESTION_UNDER_REVIEW'); ?>

									<?php } ?>

										<?php echo Lang::txt('COM_ANSWERS_ASKED_BY', $name) . ' '; ?>
										<?php echo Lang::txt('COM_ANSWERS_DATETIME_AT'); ?>
										<time datetime="<?php echo $row->created(); ?>"><?php echo $row->created('time'); ?></time>
										<?php echo Lang::txt('COM_ANSWERS_DATETIME_ON'); ?>
										<time datetime="<?php echo $row->created(); ?>"><?php echo $row->created('date'); ?></time>
										•

											<?php echo ($row->get('state')==1) ? Lang::txt('COM_ANSWERS_STATE_CLOSED') : Lang::txt('COM_ANSWERS_STATE_OPEN'); ?>

										•

											<a href="<?php echo Route::url($row->link() . '#answers'); ?>" title="<?php echo Lang::txt('COM_ANSWERS_RESPONSES_TO_THIS_QUESTION', $row->get('rcount')); ?>">
												<?php echo $row->responses->count(); ?>

								<?php if ($this->config->get('banking')) { ?>

										<?php if ($row->get('reward')) { ?>

												<?php echo $row->get('points'); ?>
												<a class="icon-coins" href="<?php echo $this->config->get('infolink'); ?>" title="<?php echo Lang::txt('COM_ANSWERS_THERE_IS_A_REWARD_FOR_ANSWERING', $row->get('points')); ?>">
													<?php echo Lang::txt('COM_ANSWERS_POINTS'); ?>

										<?php } ?>

								<?php } ?>

									<?php
									$this->view('_vote')
										->set('option', $this->option)
										->set('item', $row)
										->set('vote', $row->ballot())
										->display();
									?>

					<?php } // end foreach ?>
				<?php } else { ?>

									<?php echo Lang::txt('COM_ANSWERS_NO_RESULTS'); ?>

				<?php } // end if (count($this->results) > 0) { ?>

					<?php
					// Initiate paging
					$pageNav = $this->results->pagination;
					$pageNav->setAdditionalUrlParam('q', $this->filters['search']);
					$pageNav->setAdditionalUrlParam('filterby', $this->filters['filterby']);
					$pageNav->setAdditionalUrlParam('sortby', $this->filters['sortby']);
					$pageNav->setAdditionalUrlParam('area', $this->filters['area']);
					$pageNav->setAdditionalUrlParam('sortdir', $this->filters['sort_Dir']);
					echo $pageNav;
					?>

			</form>

<?php echo Lang::txt('COM_ANSWERS_NEED_AN_ANSWER'); ?>

					<?php echo Lang::txt('COM_ANSWERS_CANT_FIND_ANSWER', '' . Lang::txt('COM_ANSWERS_KNOWLEDGE_BASE') . '', Config::get('sitename')); ?>

<?php echo Lang::txt('COM_ANSWERS_GET_STARTED'); ?>

					<?php echo Lang::txt('COM_ANSWERS_GET_STARTED_HELP', Route::url('index.php?option=com_help&component=answers&page=index')); ?>

			<?php if ($this->config->get('banking')) { ?>

<?php echo Lang::txt('COM_ANSWERS_EARN_POINTS'); ?>

						<?php echo Lang::txt('COM_ANSWERS_START_EARNING_POINTS'); ?> <a href="<?php echo $this->config->get('infolink'); ?>"><?php echo Lang::txt('COM_ANSWERS_LEARN_MORE'); ?>.

			<?php } ?>

redpajama_set_name: RedPajamaGithub


text:
using System.Collections.Generic;

namespace Raging.Data.Schema
{
    public interface ISchemaTable
    {
        string Schema                          { get; }
        string Name                            { get; }
        string FullName                        { get; }
        bool IsView                            { get; }
        List<ISchemaColumn> Columns            { get; }
        List<ISchemaForeignKey> ForeignKeys    { get; }
        IEnumerable<ISchemaColumn> PrimaryKeys { get; }
        ISchemaColumn this[string columnName]  { get; }
    }
}


text:
package burkemw3.turboathena.testfodder.tests;

import static org.junit.Assert.assertTrue;

import org.junit.Test;

public abstract class AbstractTestBaseClass {

    @Test
    public void testInAbstractClass() {
        assertTrue(true);
    }
}


text:
require 'exel'
require 'sidekiq/testing'

Dir[File.expand_path('../../lib/**/*.rb', __FILE__)].each { |f| require f }

EXEL.logger = nil


text:
#include "stdafx.h"

#include "profilefit.h"
#include "paramset.h"
#include "materials/skincoeffs.h"
#include "parallel.h"
#include "progressreporter.h"
#include "multipole/MultipoleProfileCalculator/MultipoleProfileCalculator.h"
#include "multipole/MultipoleProfileCalculator/gaussianfit.h"
#include <map>
#include <iostream>
#include <fstream>
#include <sstream>
#include <algorithm>

using namespace std;

struct VariableParams {
	VariableParams(float f_mel, float f_eu, float f_blood, float f_ohg)
		: f_mel(f_mel), f_eu(f_eu), f_blood(f_blood), f_ohg(f_ohg) { }
	float f_mel, f_eu, f_blood, f_ohg;
};

static ostream& operator<<(ostream& os, const VariableParams& vps) {
	return os << vps.f_mel << "\t" << vps.f_eu << "\t" << vps.f_blood << "\t" << vps.f_ohg;
}

static ostream& operator<<(ostream& os, const ParamRange& pr) {
	os << pr.size();
	for (float value : pr) {
		os << "\t" << value;
	}
	return os;
}

template <class Processor>
void ForParamRange(const ParamRange& pr, const Processor& processor) {
	for (float value : pr) {
		processor(value);
	}
}

template <class Processor>
void MultipoleProfileFitRenderer::ForRanges(const Processor& p) const {
	uint32_t id = 0;
	ForParamRange(pr_f_mel, [&](float f_mel) {
		ForParamRange(pr_f_eu, [&](float f_eu) {
			ForParamRange(pr_f_blood, [&](float f_blood) {
				ForParamRange(pr_f_ohg, [&](float f_ohg) {
					p(VariableParams(f_mel, f_eu, f_blood, f_ohg), id);
					id++;
				});
			});
		});
	});
}

int MultipoleProfileFitRenderer::GetTotalNumTasks() const {
	return (int)(pr_f_mel.size() * pr_f_eu.size() * pr_f_blood.size() * pr_f_ohg.size());
}

float MultipoleProfileFitRenderer::NextParamFromId(uint32_t& id, ParamRange pr) {
	uint32_t remainder = id % (uint32_t)pr.size();
	id /= (uint32_t)pr.size();
	return pr[remainder];
}

VariableParams MultipoleProfileFitRenderer::ParamsFromId(uint32_t id) const {
	float f_ohg = NextParamFromId(id, pr_f_ohg);
	float f_blood = NextParamFromId(id, pr_f_blood);
	float f_eu = NextParamFromId(id, pr_f_eu);
	float f_mel = NextParamFromId(id, pr_f_mel);
	return VariableParams(f_mel, f_eu, f_blood, f_ohg);
}

MultipoleProfileFitRenderer::MultipoleProfileFitRenderer(const vector<SkinLayer>& layers,
	ParamRange f_mel, ParamRange f_eu, ParamRange f_blood, ParamRange f_ohg,
	uint32_t desiredLength, uint32_t segments, const string& filename,
	int idRange[2], int splitTasks, const string& pbrtFilePath)
	: layers(layers), pr_f_mel(f_mel), pr_f_eu(f_eu), pr_f_blood(f_blood), pr_f_ohg(f_ohg),
	  desiredLength(desiredLength), nSegments(segments), filename(filename),
	  splitTasks(splitTasks), pbrtFilePath(pbrtFilePath)
{
	this->idRange[0] = idRange[0];
	this->idRange[1] = idRange[1];
}

class GaussianFitTask : public Task {
public:
	static const int nLayers = 2;

	GaussianFitTask(const SampledSpectrum* mua, const SampledSpectrum* musp,
		const float* et, const float* thickness, const vector<float>& sigmas,
		SpectralGaussianCoeffs& coeffs, ProgressReporter& pr, uint32_t id,
		int sc, uint32_t desiredLength)
		: sigmas(sigmas), coeffs(coeffs), reporter(pr), id(id), sc(sc),
		  desiredLength(desiredLength)
	{
		for (int i = 0; i < nLayers; i++) {
			this->mua[i] = mua[i][sc];
			this->musp[i] = musp[i][sc];
			this->et[i] = et[i];
			this->thickness[i] = thickness[i];
		}
	}

private:
	float mua[nLayers];
	float musp[nLayers];
	float et[nLayers];
	float thickness[nLayers];
	const vector<float>& sigmas;
	SpectralGaussianCoeffs& coeffs;
	uint32_t id;
	uint32_t desiredLength;
	int sc;

	ProgressReporter& reporter;

	void Run() override;
	void DoGaussianFit(const MPC_Output* pOutput, float mfpMin, float mfpMax);
};

void GaussianFitTask::Run() {
	MPC_LayerSpec* pLayerSpecs = new MPC_LayerSpec[nLayers];
	MPC_Options options;
	options.desiredLength = desiredLength;
	options.lerpOnThinSlab = true;

	// Compute mfp
	float mfpMin = INFINITY;
	float mfpMax = 0.f;
	float mfpTotal = 0.f;
	for (int layer = 0; layer < nLayers; layer++) {
		float mfp = 1.f / (mua[layer] + musp[layer]);
		mfpTotal += mfp;
		mfpMin = min(mfpMin, mfp);
		mfpMax = max(mfpMax, mfp);
	}
	float mfp = mfpTotal / (float)nLayers;

	// Fill in layer information
	for (int layer = 0; layer < nLayers; layer++) {
		MPC_LayerSpec& ls = pLayerSpecs[layer];
		ls.g_HG = 0.f;
		ls.ior = et[layer];
		ls.mua = mua[layer];
		ls.musp = musp[layer];
		ls.thickness = thickness[layer];
	}
	// Compute desired step size
	options.desiredStepSize = 12.f * mfp / (float)options.desiredLength;

	// Do the computation
	MPC_Output* pOutput;
	MPC_ComputeDiffusionProfile(nLayers, pLayerSpecs, &options, &pOutput);
	MPC_ResampleForUniformDistanceSquaredDistribution(pOutput, pOutput->length);

	// Do gaussian fit
	DoGaussianFit(pOutput, mfpMin, mfpMax);

	MPC_FreeOutput(pOutput);

	delete [] pLayerSpecs;

	reporter.Update();
}

void GaussianFitTask::DoGaussianFit(const MPC_Output* pOutput, float mfpMin, float mfpMax) {
	int nSigmas = sigmas.size();
	const int nTargetSigmas = 6;
	const int sigmaNegExtent = nTargetSigmas / 2;
	const int sigmaPosExtent = nTargetSigmas - sigmaNegExtent - 1;

	// Compute the best fit of nTargetSigmas gaussians
	uint32 length = pOutput->length;
	vector<float> distArray(length);
	for (uint32 i = 0; i < length; i++) {
		float dsq = pOutput->pDistanceSquared[i];
		distArray[i] = sqrt(dsq);
	}
	GF_Output* pGFOutput;

	float minError = INFINITY;
	int minErrorSigmaCenter = 0;
	std::map<int, GF_Output*> oCache;
	// Try sigmas between mfpMin / 2 and mfpMax * 2
	for (int iSigmaCenter = sigmaNegExtent; iSigmaCenter < nSigmas - sigmaPosExtent; iSigmaCenter++) {
		float sigma = sigmas[iSigmaCenter];
		if (sigma < mfpMin / 2.f) continue;
		if (sigma > mfpMax * 2.f) break;
		GF_FitSumGaussians(length, &distArray[0], pOutput->pReflectance,
			nTargetSigmas, &sigmas[iSigmaCenter - sigmaNegExtent], &pGFOutput);
		if (pGFOutput->overallError < minError) {
			minError = pGFOutput->overallError;
			minErrorSigmaCenter = iSigmaCenter;
		}
		oCache[iSigmaCenter] = pGFOutput;
		pGFOutput = NULL;
	}

	// Use minErrorSigmaCenter to do fitting
	//GF_FitSumGaussians(length, &distArray[0], pOutput->pReflectance,
	//	nTargetSigmas, &sigmas[minErrorSigmaCenter - sigmaNegExtent], &pGFOutput);
	pGFOutput = oCache[minErrorSigmaCenter];

	for (int iSigma = minErrorSigmaCenter - sigmaNegExtent;
		iSigma <= minErrorSigmaCenter + sigmaPosExtent; iSigma++)
	{
		coeffs.coeffs[iSigma][sc] =
			pGFOutput->pNormalizedCoeffs[iSigma - (minErrorSigmaCenter - sigmaNegExtent)];
	}
	coeffs.error[sc] = pGFOutput->overallError;
	if (pGFOutput->overallError > 0.05f) {
		Warning("ID %d wavelength %f fit has error %.2f%%", id,
			SampledSpectrum::WaveLength(sc), pGFOutput->overallError * 100.f);
	}

	for (auto& pair : oCache)
		GF_FreeOutput(pair.second);
}

vector<Task*> MultipoleProfileFitRenderer::CreateGaussianFitTasks(const SkinCoefficients& coeffs,
	const vector<float>& sigmas, SpectralGaussianCoeffs& sgc, ProgressReporter& reporter, uint32_t id) const
{
	sgc.coeffs.resize(sigmas.size(), SampledSpectrum(0.f));

	SampledSpectrum mua[2] = {
		coeffs.mua_epi().toSampledSpectrum() / 10.f,
		coeffs.mua_derm().toSampledSpectrum() / 10.f
	};
	SampledSpectrum musp[2] = {
		coeffs.musp_epi().toSampledSpectrum() / 10.f,
		coeffs.musp_derm().toSampledSpectrum() / 10.f
	};
	float et[2] = { layers[0].ior, layers[1].ior };
	float thickness[2] = {
		layers[0].thickness / 1e6f,
		layers[1].thickness / 1e6f
	};

	vector<Task*> tasks;
	for (int sc = 0; sc < SampledSpectrum::nComponents; sc++) {
		tasks.push_back(new GaussianFitTask(mua, musp, et, thickness,
			sigmas, sgc, reporter, id, sc, desiredLength));
	}
	return tasks;
}

void MultipoleProfileFitRenderer::DoProfileFit() const {
	// All the units here are based on mm (millimeter)
	// Calculate min/max mfps
	WLDValue mfp_min(INFINITY), mfp_max(0.f);
	int nTotalTasks = 0;
	ForRanges([&] (const VariableParams& vps, uint32_t id) {
		SkinCoefficients coeffs(vps.f_mel, vps.f_eu, vps.f_blood, vps.f_ohg, 0.f, 0.f, 0.f);
		WLDValue mutp_epi = coeffs.mua_epi() + coeffs.musp_epi();
		WLDValue mutp_derm = coeffs.mua_derm() + coeffs.musp_derm();
		WLDValue mfp_epi = WLDValue(10) / mutp_epi;
		WLDValue mfp_derm = WLDValue(10) / mutp_derm;
		mfp_min = Min(Min(mfp_min, mfp_epi), mfp_derm);
		mfp_max = Max(Max(mfp_max, mfp_epi), mfp_derm);
		nTotalTasks++;
	});
	float minmfp = mfp_min.Min();
	float maxmfp = mfp_max.Max();
	Info("Min and max mfp, in millimeters: %f %f", minmfp, maxmfp);

	// Generate sigmas
	vector<float> sigmas;
	for (float sigma = minmfp / 8.f; sigma <= maxmfp * 8.f; sigma *= 2.f) {
		sigmas.push_back(sigma);
	}
	// Compute profiles and do fitting
	uint32_t idMin = (uint32_t)max(0, idRange[0]);
	uint32_t idMax = (uint32_t)(idRange[1] < 0 ? nTotalTasks : min(nTotalTasks, idRange[1]));
	if (idMax <= idMin) return;
	int nTasks = idMax - idMin;

	vector<SpectralGaussianCoeffs> gaussianCoeffs(nTasks);
	ProgressReporter reporter(nTasks * SampledSpectrum::nComponents, "Gaussian Fit");
	vector<Task*> fitTasks;
	fitTasks.reserve(nTasks * SampledSpectrum::nComponents);
	ForRanges([&] (const VariableParams& vps, uint32_t id) {
		if (id < idMin || id >= idMax) return;

		SkinCoefficients coeffs(vps.f_mel, vps.f_eu, vps.f_blood, vps.f_ohg, 0.f, 0.f, 0.f);
		vector<Task*> newTasks = CreateGaussianFitTasks(coeffs, sigmas, gaussianCoeffs[id - idMin], reporter, id);
		fitTasks.insert(fitTasks.end(), newTasks.begin(), newTasks.end());
	});
	EnqueueTasks(fitTasks);
	WaitForAllTasks();
	for (Task* task : fitTasks) {
		delete task;
	}
	MPC_ClearCache();
	reporter.Done();

	if (filename != "") {
		string filename = AbsolutePath(ResolveFilename(this->filename));
		Info("Writing to file \"%s\"", filename.c_str());
		ofstream out(filename, ios::out | ios::trunc);
		if (!out) {
			Error("Cannot open %s", filename.c_str());
			abort();
		}
		// Only print the header when range contains id 0.
		// This is to allow easier concatenation of results.
		if (idMin == 0) {
			// Output _ParamRange_s
			out << "Param\tNum Samples\tSample Points" << endl;
			out << "f_mel\t" << pr_f_mel << endl;
			out << "f_eu\t" << pr_f_eu << endl;
			out << "f_blood\t" << pr_f_blood << endl;
			out << "f_ohg\t" << pr_f_ohg << endl;
			// Output sigmas
			out << "ID\tf_mel\tf_eu\tf_blood\tf_ohg\tRGB";
			for (float sigma : sigmas) {
				out << "\t" << sigma;
			}
			out << "\tError" << endl;
		}
		for (uint32_t id = idMin; id < idMax; id++) {
			const SpectralGaussianCoeffs& coeffs = gaussianCoeffs[id - idMin];
			VariableParams vps = ParamsFromId(id);
			for (int sc = 0; sc < SampledSpectrum::nComponents; sc++) {
				out << id << "\t" << vps << "\t" << SampledSpectrum::WaveLength(sc);
				for (int i = 0; i < sigmas.size(); i++)
					out << "\t" << coeffs.coeffs[i][sc];
				out << "\t" << coeffs.error[sc] << endl;
			}
			vector<RGBSpectrum> rgbCoeffs;
			for (const SampledSpectrum& spectrum : coeffs.coeffs) {
				rgbCoeffs.push_back(spectrum.ToRGBSpectrum());
			}
			for (int rgb = 0; rgb < RGBSpectrum::nComponents; rgb++) {
				out << id << "\t" << vps << "\t" << "RGB"[rgb];
				for (int i = 0; i < sigmas.size(); i++)
					out << "\t" << rgbCoeffs[i][rgb];
				out << endl;
			}
		}
		out.close();
	}
}

static string CombineFileName(const string& prefix, int id, const string& suffix) {
	stringstream ss;
	ss << prefix << id << suffix;
	return ss.str();
}

static string GetParamRangeStringInPbrtFile(const ParamRange& pr) {
	if (pr.size() == 0) return "";

	stringstream ss;
	ss << pr[0];
	for (size_t i = 1; i < pr.size(); i++) {
		ss << " " << pr[i];
	}
	return ss.str();
}

static ostream& operator<<(ostream& os, const SkinLayer& layer) {
	return os << layer.thickness << " " << layer.ior;
}

static string GetSkinLayerStringInPbrtFile(const vector<SkinLayer>& layers) {
	if (layers.size() == 0) return "";

	stringstream ss;
	ss << layers[0];
	for (size_t i = 1; i < layers.size(); i++) {
		ss << " " << layers[i];
	}
	return ss.str();
}

void MultipoleProfileFitRenderer::DoPbrtFileSplit() const {
	int nTotalTasks = GetTotalNumTasks();
	int nSubPbrtFiles = (nTotalTasks + splitTasks - 1) / splitTasks;

	if (nSubPbrtFiles <= 1) {
		Warning("No need to split!");
		return;
	}

	// Avoid doing stupid things...
	if (nSubPbrtFiles > 20) {
		char ch;
		Warning("%d files will be generated. Are you sure? [Y/n]", nSubPbrtFiles);
		cin >> ch;
		if (ch != 'Y' && ch != 'y') {
			Warning("Aborted.");
			return;
		}
	}

	string rawPbrtPrefix = FileNameWithoutExt(pbrtFilePath) + "-";
	string pbrtFilePrefix = AbsolutePath(ResolveFilename(FileNameWithoutExt(pbrtFilePath))) + "-";
	string outFilePrefix = FileNameWithoutExt(filename) + "-";
	string pbrtFileSuffix = ".pbrt";
	string outFileSuffix = ".txt";

	string batchFilename = AbsolutePath(ResolveFilename("batch-run-" + FileNameWithoutExt(pbrtFilePath))) + ".bat";
	ofstream batout(batchFilename, ios::out | ios::trunc);
	for (int i = 0; i < nSubPbrtFiles; i++) {
		int idMin = i * splitTasks;
		int idMax = min((i + 1) * splitTasks, nTotalTasks);

		string pbrtFilename = CombineFileName(pbrtFilePrefix, i, pbrtFileSuffix);
		string outFilename = CombineFileName(outFilePrefix, i, outFileSuffix);

		Info("%d - %d -> %s", idMin, idMax, pbrtFilename.c_str());

		ofstream out(pbrtFilename, ios::out | ios::trunc);
		if (!out) {
			Error("Failed to open pbrt output file: %s", pbrtFilename.c_str());
			continue;
		}

		// Print out parameters for the profile fit
		out << "Renderer \"multipoleprofilefit\"" << endl
			<< "         \"float f_mel\" [ " << GetParamRangeStringInPbrtFile(pr_f_mel) << " ]" << endl
			<< "         \"float f_eu\" [ " << GetParamRangeStringInPbrtFile(pr_f_eu) << " ]" << endl
			<< "         \"float f_blood\" [ " << GetParamRangeStringInPbrtFile(pr_f_blood) << " ]" << endl
			<< "         \"float f_ohg\" [ " << GetParamRangeStringInPbrtFile(pr_f_ohg) << " ]" << endl
			<< "         \"skinlayer layers\" [ " << GetSkinLayerStringInPbrtFile(layers) << " ]" << endl
			<< "         \"string filename\" \"" << outFilename << "\"" << endl
			<< "         \"integer desiredProfileLength\" " << desiredLength << endl
			<< "         \"integer idrange\" [ " << idMin << " " << idMax << " ]" << endl
			<< "WorldBegin" << endl
			<< "WorldEnd" << endl;
		out.close();

		if (batout) {
			batout << "bin\\pbrt.exe --verbose scenes\\"
				<< CombineFileName(rawPbrtPrefix, i, pbrtFileSuffix) << endl;
		}
	}
	batout.close();

	Info("Generated %d files.", nSubPbrtFiles);
}

void MultipoleProfileFitRenderer::Render(const Scene* scene) {
	Info("Computing using MultipoleProfileFitRenderer.");

	if (splitTasks) {
		DoPbrtFileSplit();
	} else {
		DoProfileFit();
	}
}

Spectrum MultipoleProfileFitRenderer::Li(const Scene* scene, const RayDifferential& ray,
	const Sample* sample, RNG& rng, MemoryArena& arena,
	Intersection* isect, Spectrum* T) const
{
	return Spectrum(0.f);
}

Spectrum MultipoleProfileFitRenderer::Transmittance(const Scene* scene, const RayDifferential& ray,
	const Sample* sample, RNG& rng, MemoryArena& arena) const
{
	return Spectrum(0.f);
}

static ParamRange FindParamRange(const ParamSet& params, const string& name) {
	int nItems;
	const float* pData = params.FindFloat(name, &nItems);
	if (!pData) {
		Error("Param %s not specified for MultipoleProfileFitRenderer.", name);
		abort();
	}
	if (nItems < 1) {
		Error("Param %s doesn't specify any float.", name);
		abort();
	}
	ParamRange pr(pData, pData + nItems);
	sort(pr.begin(), pr.end());
	return pr;
}

MultipoleProfileFitRenderer* CreateMultipoleProfileFitRenderer(const ParamSet& params, const string& pbrtFilePath) {
	int nLayers;
	const SkinLayer* layers = params.FindSkinLayer("layers", &nLayers);
	if (!layers) {
		Error("No layers param set for MultipoleProfileFitRenderer.");
		abort();
	}
	if (nLayers < 2) {
		Error("Not enough layers specified for MultipoleProfileFitRenderer.");
		abort();
	}
	ParamRange pr_f_mel = FindParamRange(params, "f_mel");
	ParamRange pr_f_eu = FindParamRange(params, "f_eu");
	ParamRange pr_f_blood = FindParamRange(params, "f_blood");
	ParamRange pr_f_ohg = FindParamRange(params, "f_ohg");
	uint32_t segments = params.FindOneInt("segments", 10);
    string filename = params.FindOneString("filename", "");
	uint32_t desiredLength = params.FindOneInt("desiredProfileLength", 256);
	int nRanges;
	const int* idRanges = params.FindInt("idrange", &nRanges);
	int idRangesArray[2];
	if (!idRanges || nRanges != 2) {
		if (idRanges)
			Warning("Param \"idrange\" ignored: incorrect number of items, 2 expected.");
		idRangesArray[0] = 0;
		idRangesArray[1] = -1;
	} else {
		idRangesArray[0] = idRanges[0];
		idRangesArray[1] = idRanges[1];
	}
	int splitTasks = params.FindOneInt("splittasks", 0);
	return new MultipoleProfileFitRenderer(vector<SkinLayer>(layers, layers + nLayers),
		pr_f_mel, pr_f_eu, pr_f_blood, pr_f_ohg, desiredLength, segments, filename,
		idRangesArray, splitTasks, pbrtFilePath);
}


text:
title: Data Structure Arrays
localeTitle: 数据结构数组
---
在内部, `array`是一种数据结构,可以存储相同类型的固定大小的顺序元素集合。 `array`用于存储数据集合,但将`array`视为相同类型的变量集合通常更有用。

`array`由连续的内存位置组成。最低地址对应于第一个元素,最高地址对应于最后一个元素。

## C ++中的数组

C ++提供了一个数据结构`array` ,它存储了相同数据类型的固定大小的顺序元素集合。 `array`用于存储数据集合,但最好将`array`视为相同类型的变量集合。

#### `array`声明
```
int intarray<a href='https://repl.it/CWZE/3' target='_blank' rel='nofollow'>10]; // Declares an array of integer type of size 10 with elements having random values. Index ranges from 0 to 9(ie size-1).
 int intarray[10] = { 0 }; // Declares an array of integer of size 10 with all elements having value 0

 // Choose one the two declarations and then move ahead.
```

#### 将元素插入`array` :
```
intarray[0] = 1; // Inserts an integer value of 1 at index 0
 intarray[1] = 0; // Inserts an integer value of 0 at index 1
 intarray[2] = -1; // Inserts an integer value of -1 at index 2
 intarray[3] = 1; // Inserts an integer value of 1 at index 3
```

#### 打印`array` :
```
std::cout << intarray[0] << std::endl; // Returns 1 which is element at index of the array
 std::cout << intarray[11] << std::endl; // Would give aa "Garbage" value as there is no element at index 11 of array.
 // That memory location is beyond the range of the array.

 // To print all the elements of the array
 for(int i = 0; i < n; i++)
    std::cout << intarray[i] << std::endl;
```

#### `array`基本操作:
```
std::cout << sizeof(intarray)/sizeof(intarray[0]) << std::endl; // Returns the length of the array ie 10.
 std::cout << sizeof(intarray[0]) << std::endl; // Returns length in bytes of one array item ie 4 as it is an integer
```

:rocket:\[在Python中运行代码## Arrays Python没有本机`array`数据结构。 Python中的`array`不应与`list`混淆。 Python中`list`和`array`之间的主要区别在于`list`可以具有不同类型的值,而`array`应该具有相同类型的所有值。 #### `array`声明
```
from array import array
 intarray = array('i') # Declares an array of integer type
```

#### 将元素插入`array` :
```
intarray.append(1) # Inserts an integer value of 1 to the array
 intarray.append(0) # Inserts an integer value of 0 to the array
 intarray.append(-1) # Inserts an integer value of -1 to the array
 intarray.append(1) # Inserts an integer value of 1 to the array

 intarray.append('d') # Would give a TypeError as the array is of integer type.

 #Resolve the above error and then move ahead.
```

#### 打印`array` :
```
print(intarray) # Returns array('i', [1, 4, -1])
 print(intarray[0]) # Returns 1 which is the element at index 0 of the array
 print(intarray[3]) # Would give IndexError as there is no element at index 3 of array.

 #Resolve the above error and then move ahead.

 # To print all the elements of the array
 for i in intarray:
    print(i)
```

#### `array`基本操作:
```
len(intarray) # Returns the length of the array ie 3
 intarray.itemsize # Returns length in bytes of one array item ie 4 as it is an integer
 intarray.count(1) # Returns the number of occurrences of 1 in the array ie 2
 intarray.insert(1, 3) # Insert a new item with value x in the array before position i
 intarray.remove(1) # Remove the first occurrence of 1 from the array
 intarray.reverse() # Reverse the order of the items in the array
 intarray.pop(1) # Removes the item with the index 1 from the array and returns it
```

![:rocket:](//forum.freecodecamp.com/images/emoji/emoji_one/rocket.png?v=2 ":火箭:") [运行代码](https://repl.it/CWJB)

[官方文件](https://docs.python.org/3.5/library/array.html)