text:
import loggingstyleadapter
log = loggingstyleadapter.getLogger(__name__)

from PyQt5.QtCore import QCoreApplication, QRect, QRectF, QPointF, Qt, QObject, pyqtSignal
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *

def _(*args, **kwargs): return QCoreApplication.translate('Selector', *args, **kwargs)

class RegionSelector:
	'''Class to handle coordinating multiple selector windows for a multimonitor setup. '''

	def __init__(self, x, y, w, h, pixmap):
		self.moving = self.drawing = self.resizing = False

		self.bounds = QRectF(x, y, w, h)
		self.selectors = []
		self.selection = None
		for screen in QApplication.screens():
			# make a new selector for this screen
			# TODO: Support limited subset of screens?
			geo = screen.geometry()
			sel = Selector(geo.x(), geo.y(), geo.width(), geo.height(), pixmap, self)
			self.selectors.append(sel)
		#endfor
	#enddef

	def exec_(self):
		cPos = QCursor.pos()
		QCursor.setPos(0, 0) # XFCE workaround. In XCFE, window position is relative to the cursor position
		for sel in self.selectors: sel.show()
		QCursor.setPos(cPos)
		self.selectors[-1].exec_()
	#enddef

	def updateSelection(self):
		for s in self.selectors: s.updateSelection()
	#enddef

	def mousePressEvent(self, e):
		pos = e.globalPos()
		self.moving = self.drawing = self.resizing = False

		if self.selection is None or not self.selection.contains(pos):
			self.drawing = True
			self.selection = None
			self.selectionStart = pos
		#elif in corner
		#elif on line
		else: # in
			self.moving = True
			self.selBeforeMove = self.selection
			self.moveOrigin = pos
		#endif
		self.updateSelection()
	#enddef

	def mouseMoveEvent(self, e):
		pos = e.globalPos()
		if self.drawing:
			if pos.x() != self.selectionStart.x() and pos.y() != self.selectionStart.y():
				self.selection = QRectF(QPointF(self.selectionStart), QPointF(pos)).normalized()
				self.selection = self.selection.intersected(self.bounds)
				self.updateSelection()
			#endif
		elif self.moving:
			delta = pos - self.moveOrigin
			moved = self.selBeforeMove.translated(delta)

			# TODO: this cause the bounds to be "sticky", since trying to move back after pushing it 50px off the edge
			# means we must re-traverse the other 49 "off screen" pixels before we get some visible movement
			minX, maxX = self.bounds.x(), self.bounds.x() + self.bounds.width() - moved.width()
			minY, maxY = self.bounds.y(), self.bounds.y() + self.bounds.height() - moved.height()

			moved.moveTo(min(max(minX, moved.x()), maxX), min(max(minY, moved.y()), maxY))

			self.selection = moved.intersected(self.bounds)
			self.updateSelection()
		#endif
	#enddef

	def mouseReleaseEvent(self, e):
		self.moving = self.drawing = self.resizing = False

		self.updateSelection()
	#enddef

	def keyReleaseEvent(self, event):
		if event.key() == Qt.Key_Escape:
			self.selection = None
			self.close()
		elif event.key() in (Qt.Key_Enter, Qt.Key_Return):
			if self.selection:
				self.close()
			#endif
		#endif
	#enddef

	def close(self):
		for s in self.selectors: s.close()
	#enddef
#endclass

class Selector(QDialog):
	def __init__(self, x, y, width, height, pixmap, region):
		super().__init__()
		log.debug('Opening selector at {x}, {y}: {w} {h}', x=x, y=y, w=width, h=height)
		self.region = region
		# ui setup
		self.setWindowTitle(_('Select a region'))
		self.setWindowFlags(self.windowFlags() | Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
		self.setFocusPolicy(Qt.StrongFocus)

		bgImg = QGraphicsPixmapItem(pixmap)

		self.view = QGraphicsView(self)
		self.view.setStyleSheet("QGraphicsView { border-style: none; }")
		self.view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
		self.view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

		self.graphics = QGraphicsScene(self.view)
		self.graphics.addItem(bgImg)
		self.view.setScene(self.graphics)

		self.view.setGeometry(0, 0, width, height)
		self.view.setSceneRect(x, y, width, height)

		self.bounds = QRect(x, y, width, height)
		self.rubber = OccultingRubberband(self, QColor(100,100,100,140), QColor('red'), 15,
			'Select an area using the mouse.\nPress Enter to take a screenshot or Esc to exit.',
			 QColor(28,28,28,220), QColor(150,150,150,240), region)
		self.rubber.setSceneRect(QRectF(self.bounds))
		self.rubber.setGeometry(0, 0, width, height)
	#enddef

	def showEvent(self, e):
		self.raise_()
		self.setGeometry(self.bounds)
		self.repaint()
		#self.setWindowState(Qt.WindowFullScreen)
	#enddef

	def keyReleaseEvent(self, event):
		self.region.keyReleaseEvent(event)
		super().keyReleaseEvent(event)
	#enddef

	def updateSelection(self):
		self.rubber._updateLayout()
	#enddef
#endclass

class OccultingRubberband(QGraphicsView):
	''' Implementation of a rubber band that grays out area around the selection '''
	def __init__(self, parent, occultColor, lineColor, handleSize, helpText, textBgColor, textColor, region):
		super().__init__(parent)
		self.region = region
		self.setCursor(Qt.OpenHandCursor)

		self.theScene = QGraphicsScene(self)
		self.setStyleSheet("QGraphicsView { border-style: none; background-color: transparent;}")
		self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
		self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

		self.selectionView = QGraphicsItemGroup()
		self.theScene.addItem(self.selectionView)

		self.occulting = [QGraphicsRectItem() for i in range(4)]
		for o in self.occulting:
			o.setBrush(occultColor)
			o.setPen(QPen(Qt.NoPen))
			o.setCursor(Qt.CrossCursor)
			self.selectionView.addToGroup(o)
		#endfor

		self.lines = [QGraphicsLineItem() for i in range(4)]
		for l, cursor in zip(self.lines, [Qt.SizeHorCursor, Qt.SizeVerCursor]*2):
			l.setPen(QPen(lineColor, 2))
			#l.setCursor(cursor)
			self.selectionView.addToGroup(l)
		#endfor

		self.corners = [QGraphicsRectItem() for i in range(4)]
		for c, cursor in zip(self.corners, [Qt.SizeFDiagCursor, Qt.SizeBDiagCursor]*2):
			c.setBrush(QBrush(occultColor))
			c.setPen(QPen(lineColor, 2))
			c.setCursor(cursor)
			#self.selectionView.addToGroup(c)
		#endfor

		# Displayed when there's no selection
		self.noSelectionHighlight = QGraphicsRectItem()
		self.noSelectionHighlight.setCursor(Qt.CrossCursor)
		self.noSelectionHighlight.setPen(QPen(Qt.NoPen))
		self.noSelectionHighlight.setBrush(QBrush(occultColor))
		self.theScene.addItem(self.noSelectionHighlight)

		helpTextItem = QGraphicsTextItem()
		helpFont = QFont()
		helpFont.setPointSize(20)
		helpTextItem.setFont(helpFont)
		helpTextItem.setDefaultTextColor(textColor)
		helpTextItem.setTextWidth(1000) # TODO: Get this from the geometry
		helpTextItem.document().setDefaultTextOption(QTextOption(Qt.AlignCenter))
		helpTextItem.setPlainText(helpText)

		helpRect = helpTextItem.boundingRect()

		helpRectPath = QPainterPath()
		helpRectPath.addRoundedRect(helpRect.x() - 10, helpRect.y() - 10, helpRect.width() + 20, helpRect.height() + 20, 10, 10)

		helpRectItem = QGraphicsPolygonItem()
		helpRectItem.setPolygon(helpRectPath.toFillPolygon(QTransform()))
		helpRectItem.setBrush(textBgColor)

		self.theScene.addItem(helpRectItem)
		self.theScene.addItem(helpTextItem)

		self.helpOverlay = self.theScene.createItemGroup([helpTextItem, helpRectItem])
		self.helpOverlay.setZValue(2)
		helpTextItem.setZValue(1)

		self.noSelectionOverlay = self.noSelectionHighlight # in case we want to add more here later

		# This is so we get a cross cursor while drawing
		# without this, the rubber band's resize cursors take over
		# as the user is drawing initially.
		self.drawingOverlay = QGraphicsRectItem()
		self.drawingOverlay.setCursor(Qt.CrossCursor)
		self.drawingOverlay.setPen(QPen(Qt.NoPen))
		self.theScene.addItem(self.drawingOverlay)

		self.setScene(self.theScene)
		self.handleSize = handleSize
	#enddef

	def _updateLayout(self):
		selection = self.region.selection

		geo = self.sceneRect()

		self.drawingOverlay.setVisible(self.region.drawing)
		if self.region.drawing: self.helpOverlay.setVisible(False)
		self.setCursor(Qt.ClosedHandCursor if self.region.moving else Qt.OpenHandCursor)

		if selection is None or not selection.intersects(geo):
			self.selectionView.setVisible(False)
			self.noSelectionOverlay.setVisible(True)
		else:
			# Get the bounds of selection for this window's area
			intersected = selection.intersected(geo)

			# Calculate the bounds of the occulting rectangles
			left, top, right, bottom = self.occulting

			leftBound = selection.x() # X coord of the left edge of selection
			topBound = selection.y() # Y coord of the top edge of selection
			rightBound = leftBound + selection.width() # X coord of the right edge of selection
			bottomBound = topBound + selection.height() # relative Y coord of the bottom edge of selection

			if leftBound > geo.x(): # Only draw occulting if selection starts to our right
				left.setRect(geo.x(), 0, leftBound - geo.x(), geo.height())
				left.setVisible(True)
			else: left.setVisible(False)

			if topBound > geo.y(): # Only draw top items if selection starts below our top
				top.setRect(leftBound, geo.y(), rightBound - leftBound, topBound - geo.y())
				top.setVisible(True)
			else: top.setVisible(False)

			if rightBound < geo.x() + geo.width(): # Only draw right if selection ends to the left of out right edge
				right.setRect(rightBound, geo.y(), geo.x() + geo.width() + rightBound, geo.height())
				right.setVisible(True)
			else: right.setVisible(False)

			if bottomBound < geo.y() + geo.height(): # Only draw bottom if selection ends above our bottom edge
				bottom.setRect(leftBound, bottomBound, rightBound - leftBound, geo.y() + geo.height() - bottomBound)
				bottom.setVisible(True)
			else: bottom.setVisible(False)

			offset = 2/2 # Half of pen width
			leftBound -= offset
			topBound -= offset
			rightBound += offset
			bottomBound += offset

			left, top, right, bottom = self.lines
			left.setLine(leftBound, topBound, leftBound, bottomBound)
			top.setLine(leftBound, topBound, rightBound, topBound)
			right.setLine(rightBound, topBound, rightBound, bottomBound)
			bottom.setLine(leftBound, bottomBound, rightBound, bottomBound)

			left,top, right, bottom = self.corners
			left.setRect(leftBound, topBound, self.handleSize, self.handleSize)
			top.setRect(rightBound - self.handleSize, topBound, self.handleSize, self.handleSize)
			right.setRect(rightBound - self.handleSize, bottomBound - self.handleSize, self.handleSize, self.handleSize)
			bottom.setRect(leftBound, bottomBound - self.handleSize, self.handleSize, self.handleSize)

			self.selectionView.setVisible(True)
			self.noSelectionOverlay.setVisible(False)
		#endif
	#enddef

	def resizeEvent(self, e):
		geo = QRectF(self.sceneRect())
		self.drawingOverlay.setRect(geo)
		self.noSelectionHighlight.setRect(geo)

		hr = self.helpOverlay.boundingRect()
		hr.moveCenter(geo.center())
		self.helpOverlay.setPos(hr.x(), hr.y())

		self._updateLayout()
	#enddef

	def mousePressEvent(self, e):
		self.region.mousePressEvent(e)
		super().mousePressEvent(e)
	#enddef

	def mouseMoveEvent(self, e):
		self.region.mouseMoveEvent(e)
		super().mouseMoveEvent(e)
	#enddef

	def mouseReleaseEvent(self, e):
		self.region.mouseReleaseEvent(e)
		super().mouseReleaseEvent(e)
	#enddef
#endclass


text:
#import <UIKit/UIKit.h>
#import "HUBaseViewController.h"
#import "Models.h"

typedef NS_ENUM(NSInteger, ImageUploadType) {
    UploadTypeUploadToWall,
    UploadTypeUploadAsUserAvatar
};

@protocol HUImageUploadViewConrollerDelegate;

@interface ImageUploadVC : HUBaseViewController {

    UIImage *_image;
    ImageUploadType _uploadType;

    ModelUser *_targetUser;
    ModelGroup *_targetGroup;

}

-(id) initWithImage:(UIImage *)image uploadType:(ImageUploadType) uploadType;

@property (nonatomic, weak) id<HUImageUploadViewConrollerDelegate> delegate;
@property (nonatomic, strong) ModelGroup *targetGroup;
@property (nonatomic, strong) ModelUser *targetUser;

@end

//@protocol HUImageUploadViewConrollerDelegate <NSObject>
//
//- (void) imageUploadViewController:(ImageUploadVC *)viewController
//                   didUpdateObject:(HUBaseModel *)object;
//
//@end

redpajama_set_name: RedPajamaGithub


text:
require 'pygments'
require 'set'

module Retter
  module StaticSite
    class Markdown < Redcarpet::Markdown
      class PygmentsRenderer < Redcarpet::Render::HTML
        LANGUAGES = Set.new(Pygments.lexers.map {|_, l| l[:aliases] }.flatten)

        def block_code(code, lang)
          lang = LANGUAGES.include?(lang) ? lang : 'text'

          Pygments.highlight(code, lexer: lang, formatter: 'html', options: {encoding: 'utf-8'})
        end
      end
    end
  end
end


text:
<?xml version="1.0" encoding="utf-8"?>
<!--This is a Regression Tester export.-->
<export version="3.1">
	<test name="rttests.table_varchar2_index_by_vrchr" creation_date="12/01/2016 20:14:27" guid="09be3c64-4dd8-46c9-9457-4e1f6657aa1a" unit_schema="RTTESTS" unit_name="TABLE_VARCHAR2_INDEX_BY_VRCHR" unit_method="" unit_type="FUNCTION" overload="0" is_pipelined_function="">
		<description />
		<plsql_declare />
		<plsql_block />
		<arguments>
			<argument argument_name="param1" in_out="IN" sequence="3" data_level="0" position="1" data_type="PL/SQL TABLE" pls_type="RTTESTS.DEFINITIONS.T_ARRVARCHAR2SINDEXEDBYVARCHR" can_default="N">
				<arguments>
					<argument argument_name="$$param1" in_out="IN" sequence="4" data_level="1" position="1" data_type="VARCHAR2" pls_type="VARCHAR2" can_default="N" />
				</arguments>
			</argument>
			<argument argument_name="v_returnvalue" in_out="RETURN" sequence="1" data_level="0" position="0" data_type="PL/SQL TABLE" pls_type="RTTESTS.DEFINITIONS.T_ARRVARCHAR2SINDEXEDBYVARCHR" can_default="N">
				<arguments>
					<argument argument_name="$$" in_out="RETURN" sequence="2" data_level="1" position="1" data_type="VARCHAR2" pls_type="VARCHAR2" can_default="N" />
				</arguments>
			</argument>
		</arguments>
		<scenario_groups>
			<scenario_group name="General Tests" reopen_connection_before_every_scenario="N" rollback_afterwards="Y" max_allowed_run_time_in_seconds="300" guid="78f7c5eb-65d2-4ad0-a099-fd6d4ae51a3c">
				<description />
				<scenario_group_declare />
				<scenario_group_startup />
				<scenario_startup />
				<post_param_assignment />
				<pre_user_defined_checks />
				<scenario_teardown />
				<scenario_group_teardown />
				<scenarios />
				<user_defined_checks />
				<library_items />
			</scenario_group>
		</scenario_groups>
	</test>
</export>


text:
module.exports = {
  extends: ['@repodog/eslint-config']
};


text:
#ifndef __PCI_IRQ_H__
#define	__PCI_IRQ_H__

struct pci_devinst;

void	pci_irq_assert(struct pci_devinst *pi);
void	pci_irq_deassert(struct pci_devinst *pi);
void	pci_irq_init(struct vmctx *ctx);
void	pci_irq_reserve(int irq);
void	pci_irq_use(int irq);
int	pirq_alloc_pin(struct pci_devinst *pi);
int	pirq_irq(int pin);
uint8_t	pirq_read(int pin);
void	pirq_write(struct vmctx *ctx, int pin, uint8_t val);

#endif


text:
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Helpers;

use App\Http\Requests;
use App\Http\Controllers\Controller;

use App\Models\User;
use App\Models\Event;
use App\Models\Slot;
use Carbon\Carbon;

class ReportController extends Controller
{
    // Require admin authentication
    public function __construct()
    {
        $this->middleware('auth');
        $this->middleware('lead');
        $this->middleware('bindings');
    }

    // Main page for reports
    public function reportList()
    {
        $events = Event::orderBy('start_date', 'desc')->take(10)->get();
        return view('pages/admin/report-list', compact('events'));
    }

    // TODO: Use a real search engine like ElasticSearch or SOLR
    public function searchUsers(Request $request)
    {
        $search = $request->get('search');
        $users = [];

        if(is_numeric($search))
        {
            $userSearch = [User::find($search)];
        }
        else
        {
            $userSearch = User::where('name', 'like', "%{$search}%")->orWhere('email', 'like', "%{$search}%")->take(5)->get();
        }

        foreach($userSearch as $user)
        {
            $users[] =
            [
                'id' => $user->id,
                'name' => $user->name,
                'full_name' => $user->data()->exists() && $user->data->full_name ? $user->data->full_name : '',
                'burner_name' => Helpers::displayName($user),
                'email' => $user->email
            ];
        }

        return json_encode($users);
    }

    public function getDepartments(Request $request)
    {
        $id = $request->get('event');
        $event = Event::findOrFail($id);
        $departments = [];

        foreach($event->departments()->orderBy('name', 'asc')->get() as $department)
        {
            $departments[] =
            [
                'id' => $department->id,
                'name' => $department->name
            ];
        }

        return json_encode($departments);
    }

    public function getDays(Request $request)
    {
        $id = $request->get('event');
        $event = Event::findOrFail($id);
        $days = [];

        foreach($event->days() as $day)
        {
            $day->date = $day->date->format('m/d/Y');
            $days[] = $day;
        }

        return json_encode($days);
    }

    public function generateReport(Request $request)
    {
        $event = Event::find($request->get('event'));
        $type = $request->get('type');

        if(empty($event))
        {
            $request->session()->flash('error', 'An event must be selected to generate reports.');
            return redirect()->back();
        }

        if(empty($type))
        {
            $request->session()->flash('error', 'A report type must be must be selected.');
            return redirect()->back();
        }

        if($type == 'user')
        {
            return $this->userReport($event, $request);
        }
        elseif($type == 'department')
        {
            return $this->departmentReport($event, $request);
        }
        elseif($type == 'misc')
        {
            $report = $request->get('misc-reports');

            if(empty($report))
            {
                $request->session()->flash('error', 'You must select a report to generate.');
                return redirect()->back();
            }

            if($report == 'hours-volunteered')
            {
                $this->hoursVolunteeredReport($event, $request);
            }
            elseif($report == 'shifts-filled')
            {
                $this->shiftsFilledReport($event, $request);
            }
            elseif($report == 'popular-camps')
            {
                $this->popularCampsReport($event, $request);
            }
        }
    }

    private function userReport($event, $request)
    {
        if($request->get('user-options') == 'specific')
        {
            $ids = $request->get('user-report');

            if(empty($ids))
            {
                $request->session()->flash('error', 'No user selected. Please use the checkboxes to generate reports for specific users.');
                return redirect()->back();
            }

            // Select users based on specified user IDs
            $users = User::whereIn('id', $ids)->get();
        }
        else
        {
            // Select all users
            $users = User::get();
        }

        // Select all scheduled shifts in the selected event
        $schedule_ids = [];

        foreach($event->departments as $department)
        {
            foreach($department->schedule as $schedule)
            {
                $schedule_ids[] = $schedule->id;
            }
        }

        $columns =
        [
            'user' => 'Username',
            'first_name' => 'First Name',
            'last_name' => 'Last Name',
            'burner_name' => 'Playa Name',
            'email' => 'Email',
            'day' => 'Day of the Week',
            'date' => 'Date',
            'department' => 'Department',
            'shift' => 'Shift',
            'start_time' => 'Start Time',
            'end_time' => 'End Time'
        ];

        $data = [];

        foreach($users as $user)
        {
            $name = ['first' => '', 'last' => ''];

            if($user->data()->exists())
            {
                $name = $this->splitName($user->data->full_name);
            }

            $slots = $user->slots()->whereIn('schedule_id', $schedule_ids)->get();

            foreach($slots as $slot)
            {
                $date = new Carbon($slot->start_date);

                $data[] =
                [
                    'user' => $user->name,
                    'first_name' => $name['first'],
                    'last_name' => $name['last'],
                    'burner_name' => Helpers::displayName($user),
                    'email' => $user->email,
                    'day' => $date->formatLocalized('%A'),
                    'date' => $date->format('m/d/Y'),
                    'department' => $slot->department->name,
                    'shift' => $slot->schedule->shift->name,
                    'start_time' => $slot->start_time,
                    'end_time' => $slot->end_time
                ];
            }
        }

        $this->generateCSV('Volunteer DB User Report - ' . date('Y-m-d H:i:s'), $columns, $data);
    }

    private function departmentReport($event, $request)
    {
        if($request->get('department-options') == 'specific')
        {
            $ids = $request->get('department-report');

            if(empty($ids))
            {
                $request->session()->flash('error', 'No departments selected. Please use the checkboxes to generate reports for specific departments.');
                return redirect()->back();
            }

            // Select deparatments based on specified IDs
            $departments = $event->departments()->whereIn('id', $ids)->get();
        }
        else
        {
            // Select all departments
            $departments = $event->departments;
        }

        // Return a printable format?
        if($request->get('department-output') == 'printable')
        {
            return view('pages/admin/report-departments-printable', compact('event', 'departments'));
        }

        // Otherwise, start preparing the CSV data
        $columns =
        [
            'department' => 'Department',
            'shift' => 'Shift',
            'day' => 'Day of the Week',
            'date' => 'Date',
            'start_time' => 'Start Time',
            'end_time' => 'End Time',
            'user' => 'Username',
            'email' => 'Email',
            'first_name' => 'First Name',
            'last_name' => 'Last Name',
            'burner_name' => 'Playa Name'
        ];

        $data = [];

        foreach($departments as $department)
        {
            foreach($department->slots as $slot)
            {
                $date = new Carbon($slot->start_date);

                $row =
                [
                    'department' => $department->name,
                    'shift' => $slot->schedule->shift->name,
                    'day' => $date->formatLocalized('%A'),
                    'date' => $date->format('m/d/Y'),
                    'start_time' => $slot->start_time,
                    'end_time' => $slot->end_time
                ];

                if($slot->user()->exists())
                {
                    $row['user'] = $slot->user->name;
                    $row['email'] = $slot->user->email;

                    if($slot->user->data()->exists())
                    {
                        $name = $this->splitName($slot->user->data->full_name);
                        $row['first_name'] = $name['first'];
                        $row['last_name'] = $name['last'];
                        $row['burner_name'] = $slot->user->data->burner_name;
                    }
                }

                $data[] = $row;
            }
        }

        $this->generateCSV('Volunteer DB Department Report - ' . date('Y-m-d H:i:s'), $columns, $data);
    }

    private function hoursVolunteeredReport($event, $request)
    {
        // Set up CSV output variables
        $columns =
        [
            'last_name' => 'Last name',
            'first_name' => 'First name',
            'user' => 'Username',
            'email'=> 'Email',
            'burner_name' => 'Playa name',
            'shifts' => 'Total number of shifts',
            'hours' => 'Total hours volunteered'
        ];

        $data = [];

        // Select all shifts in the selected event
        $schedule_ids = [];

        foreach($event->departments as $department)
        {
            foreach($department->schedule as $schedule)
            {
                $schedule_ids[] = $schedule->id;
            }
        }

        // Select all users
        $users = User::get();

        // Loop through users to check the slots they've signed up for
        foreach($users as $user)
        {
            $name = ['first' => '', 'last' => ''];

            if($user->data()->exists())
            {
                $name = $this->splitName($user->data->full_name);
            }

            $slots = $user->slots()->whereIn('schedule_id', $schedule_ids)->get();
            $hoursVolunteered = 0;
            $slotsVolunteered = 0;

            // Calculate how long each shift was
            foreach($slots as $slot)
            {
                $duration = Slot::timeToSeconds($slot->schedule->duration) / 60 / 60;

                $hoursVolunteered += $duration;
                $slotsVolunteered++;
            }

            // Skip users that did not volunteer
            if(!$slotsVolunteered)
            {
                continue;
            }

            // Add data to export
            $data[] =
            [
                'last_name' => $name['last'],
                'first_name' => $name['first'],
                'user' => $user->name,
                'email'=> $user->email,
                'burner_name' => Helpers::displayName($user),
                'shifts' => $slotsVolunteered,
                'hours' => $hoursVolunteered
            ];
        }

        // Create collection from saved data
        $collection = collect($data);

        // Sort the collection and save it back into the data array
        $data = $collection->sortBy('last_name')->sortByDesc('hours');

        $this->generateCSV('Volunteer DB Hours Volunteered Report - ' . date('Y-m-d H:i:s'), $columns, $data);
    }

    private function shiftsFilledReport($event, $request)
    {
        // Set up CSV output variables
        $columns =
        [
            'department' => 'Department',
            'filled' => 'Shifts Filled',
            'empty' => 'Shifts Empty',
            'percent' => 'Percent Filled',
        ];

        $data = [];
        $total = ['filled' => 0, 'empty' => 0];

        // Loop through event departments
        foreach($event->departments as $department)
        {
            $schedule_ids = [];

            foreach($department->schedule as $schedule)
            {
                $schedule_ids[] = $schedule->id;
            }

            // Get all slots for this department
            $filled = Slot::whereIn('schedule_id', $schedule_ids)->whereNotNull('user_id')->get();
            $empty = Slot::whereIn('schedule_id', $schedule_ids)->whereNull('user_id')->get();

            $total['filled'] += $filled->count();
            $total['empty'] += $empty->count();

            $data[] =
            [
                'department' => $department->name,
                'filled' => $filled->count(),
                'empty' => $empty->count(),
                'percent' => ($filled->count() || $empty->count()) ? number_format($filled->count() / ($filled->count() + $empty->count()) * 100, 2) : 0,
            ];
        }

        // Create collection from saved data
        $collection = collect($data);

        // Sort the collection and save it back into the data array
        $data = $collection->sortByDesc('percent');

        // Add the total to the end of the dataset
        $data[] =
        [
            'department' => 'Total',
            'filled' => $total['filled'],
            'empty' => $total['empty'],
            'percent' => number_format($total['filled'] / ($total['filled'] + $total['empty']) * 100, 2)
        ];

        $this->generateCSV('Volunteer DB Shifts Filled Report - ' . date('Y-m-d H:i:s'), $columns, $data);
    }

    private function popularCampsReport($event, $request)
    {
        // Select all users
        $users = User::get();

        // Select all scheduled shifts in the selected event
        $schedule_ids = [];

        foreach($event->departments as $department)
        {
            foreach($department->schedule as $schedule)
            {
                $schedule_ids[] = $schedule->id;
            }
        }

        $columns =
        [
            'camp' => 'Camp Name',
            'users' => 'Number of Volunteers',
            'slots' => 'Number of Shifts Taken',
            'hours' => 'Total hours volunteered'
        ];

        $data = [];
        $camps = [];

        // Loop through all users to see what camps they belong to
        foreach($users as $user)
        {
            $name = ['first' => '', 'last' => ''];

            if($user->data()->exists())
            {
                $name = $this->splitName($user->data->full_name);
            }

            // Make sure this user has actually volunteered for the selected event
            $slots = $user->slots()->whereIn('schedule_id', $schedule_ids)->get();
            $hoursVolunteered = 0;

            if($slots->count())
            {
                foreach ($slots as $slot)
                {
                    $duration = Slot::timeToSeconds($slot->schedule->duration) / 60 / 60;
                    $hoursVolunteered += $duration;
                }

                if(!empty($user->data) && !empty($user->data->camp))
                {
                    $camp = preg_replace("/[^a-z0-9]/", "", strtolower($user->data->camp));
                }
                else
                {
                    $camp = "none";
                }

                if(!isset($camps[$camp]))
                {
                    $camps[$camp] = ['name' => $user->data->camp, 'users' => 0, 'slots' => 0, 'hours' => 0];
                }

                $camps[$camp]['users']++;
                $camps[$camp]['slots'] += $slots->count();
                $camps[$camp]['hours'] += $hoursVolunteered;
            }
        }

        // Loop through camp statistics to generate a CSV
        foreach($camps as $camp)
        {
            $data[] =
            [
                'camp' => $camp['name'],
                'users' => $camp['users'],
                'slots' => $camp['slots'],
                'hours' => $camp['hours']
            ];
        }

        // Create collection from saved data
        $collection = collect($data);

        // Sort the collection and save it back into the data array
        $data = $collection->sortByDesc('slots');

        $this->generateCSV('Volunteer DB Camps Report - ' . date('Y-m-d H:i:s'), $columns, $data);
    }

    private function generateCSV($filename, $columns, $data)
    {
        $filename = $filename . '.csv';

        header('Content-Type: text/csv');
        header('Content-Disposition: attachment;filename="' . $filename . '"');

        $columnNames = array_values($columns);

        $file = fopen('php://output', 'w');
        fputcsv($file, $columnNames);

        foreach($data as $row)
        {
            $output = [];

            foreach($columns as $column => $columnName)
            {
                if(isset($row[$column]))
                {
                    $output[] = $row[$column];
                }
                else
                {
                    $output[] = '';
                }
            }

            fputcsv($file, $output);
        }

        fclose($file);
    }

    private function splitName($name)
    {
        $name = explode(' ', $name);

        // If the user only entered one name
        if(count($name) == 1)
        {
            $split =
            [
                'first' => $name[0],
                'last' => "",
            ];
        }
        else
        {
            $split =
            [
                'first' => implode(' ', array_slice($name, 0, -1)),
                'last' => implode(' ', array_slice($name, -1))
            ];
        }

        return $split;
    }
}