text:
package scalan.primitives

import scalan._
import scala.reflect.runtime.universe._
import scalan.util.CollectionUtil._
import scalan.common.OverloadHack._
import scalan.compilation.{GraphVizConfig, GraphVizExport}
import scalan.staged.Expressions

/**
 The code is inspired by LMS structs and is used in Scalan with the same semantics
 in order to easily translate operations to the equivalents via LmsBridge.
 Their usage in Scalan is limited to be consistent with functional semantics of Scalan.
 Don't expect everything possible in LMS to be also possible in Scalan in the same way.
 There are changes in the code:
 - Sym -> Exp
 - Manifest -> Elem
 - infix -> implicit class
 - no SourceContext, withPos
 - mirroring implemented in Scalan way (though consistent with LMS)
 */
trait Structs extends Base { self: StructsDsl with Scalan =>
}

trait StructsDsl extends Structs with StructItemsDsl with StructKeysDsl { self: StructsDsl with Scalan =>
  // TODO consider if T type parameter is needed here and for AbstractStruct
  // It's only useful if we'll have some static typing on structs later (Shapeless' records?)
  abstract class StructTag[T <: Struct](implicit val typeTag: TypeTag[T]) {
    override def equals(other: Any): Boolean =
      !!!("StructTag.equals must be overridden so that the outer instances aren't compared")
  }
  case class SimpleTag[T <: Struct](name: String)(implicit typeTag: TypeTag[T]) extends StructTag[T] {
    override def equals(other: Any) = other match {
      case tag: StructsDsl#SimpleTag[_] => name == tag.name && typeTag == tag.typeTag
      case _ => false
    }
  }
  object SimpleTag {
    def apply[T <: Struct](implicit tag: TypeTag[T]): SimpleTag[T] = SimpleTag[T](tag.tpe.typeSymbol.name.toString)
  }
  val defaultStructTag = SimpleTag[Struct]

  protected def baseStructName(tag: StructTag[_]) = tag match {
    case `defaultStructTag` => ""
    case SimpleTag(name) => s"$name "
    // Intentionally no case _, add something here or override when extending StructTag!
  }

  type StructField = (String, Rep[Any])
  trait Struct {
    def tag: StructTag[_] // TODO add type argument?
//    def keys: Rep[KeySet]
//    def values: Rep[HList]
    def fields: Seq[StructField]
  }

  case class StructElem[T <: Struct](structTag: StructTag[T], fields: Seq[(String, Elem[_])]) extends Elem[T] {
    override def isEntityType = fields.exists(_._2.isEntityType)
    lazy val tag = structTag.typeTag
    protected def getDefaultRep =
      struct(structTag, fields.map { case (fn,fe) => (fn, fe.defaultRepValue) }: _*)
    def get(fieldName: String): Option[Elem[_]] = fields.find(_._1 == fieldName).map(_._2)
    def apply(fieldIndex: Int): Elem[_] = fields(fieldIndex)._2
    def apply(fieldName: String): Elem[_] = fields.find(_._1 == fieldName).map(_._2).get
    def fieldNames = fields.map(_._1)
    def fieldElems: Seq[Elem[_]] = fields.map(_._2)
    def isEqualType(tuple: Seq[Elem[_]]) = {
      fields.length == tuple.length && fields.zip(tuple).forall { case ((fn,fe), e) => fe == e }
    }
    override def getName = {
      s"${baseStructName(structTag)}$fieldsString"
    }
    def fieldsString = s"{${fields.map { case (fn,fe) => s"$fn: ${fe.name}"}.mkString("; ")}}"
    def findFieldIndex(fieldName: String): Int = fields.iterator.map(_._1).indexOf(fieldName)
  }
  implicit def StructElemExtensions[T <: Struct](e: Elem[T]): StructElem[T] = e.asInstanceOf[StructElem[T]]

  def structElement[T <: Struct](tag: StructTag[T], fields: Seq[(String, Elem[_])]): StructElem[T] =
    if (cacheElems)
      cachedElem[StructElem[T]](tag, fields)
    else
      StructElem(tag, fields)

  def structElement(fields: Seq[(String, Elem[_])]): StructElem[Struct] =
    structElement(defaultStructTag, fields)

  def structElementFor[T <: Struct : TypeTag](fields: Seq[(String, Elem[_])]): StructElem[T] =
    structElement(SimpleTag[T], fields)
  /**
    * Get tuple field name by index
    */
  def tupleFN(fieldIndex: Int) = s"_$fieldIndex"

  def tupleStructElement(fieldElems: Elem[_]*)(implicit o: Overloaded1): StructElem[Struct] = {
    val fields = fieldElems.zipWithIndex.map { case (f, i) => tupleFN(i + 1) -> f }
    // TODO add tupleTag(n)?
    structElement(defaultStructTag, fields)
  }

  def tuple2StructElement[A:Elem, B:Elem]: StructElem[Struct] =
    tupleStructElement(element[A], element[B])

  def tuple3StructElement[A:Elem, B:Elem, C:Elem]: StructElem[Struct] =
    tupleStructElement(element[A], element[B], element[C])

  case class StructToPairIso[A1, A2, B1, B2](iso1: Iso[A1, B1], iso2: Iso[A2, B2])
    extends IsoUR[Struct, (B1, B2)] {
    override def equals(other: Any) = other match {
      case iso: StructsDsl#StructToPairIso[_, _, _, _] =>
        (this eq iso) || (iso1 == iso.iso1 && iso2 == iso.iso2)
      case _ => false
    }

    implicit def eA1 = iso1.eFrom
    implicit def eA2 = iso2.eFrom
    implicit def eB1 = iso1.eTo
    implicit def eB2 = iso2.eTo
    lazy val eFrom = tuple2StructElement(iso1.eFrom, iso2.eFrom)
    lazy val eTo = element[(B1, B2)]
    lazy val selfType = new ConcreteIsoElem[Struct, (B1, B2), StructToPairIso[A1, A2, B1, B2]](eFrom, eTo).
      asElem[IsoUR[Struct, (B1, B2)]]

    override def from(p: Rep[(B1, B2)]) =
      struct(tupleFN(1) -> iso1.from(p._1), tupleFN(2) -> iso2.from(p._2))

    override def to(struct: Rep[Struct]) = {
      Pair(iso1.to(struct(1).asRep[A1]), iso2.to(struct(2).asRep[A2]))
    }
  }

  def structToPairIso[A1, A2, B1, B2](iso1: Iso[A1, B1], iso2: Iso[A2, B2]): Iso[Struct, (B1, B2)] =
    reifyObject(StructToPairIso[A1, A2, B1, B2](iso1, iso2))

  def structToPairIso[A:Elem,B:Elem]: Iso[Struct, (A, B)] = structToPairIso[A,B,A,B](identityIso[A], identityIso[B])
  def structToPairIso[A,B](pe: Elem[(A,B)]): Iso[Struct, (A, B)] = structToPairIso[A,B](pe.eFst, pe.eSnd)

  case class StructIso[S <: Struct, T <: Struct](eFrom: StructElem[S], eTo: StructElem[T], itemIsos: Seq[Iso[_,_]])
    extends IsoUR[S, T] {
    assert(eFrom.isEqualType(itemIsos.map(_.eFrom)))
    assert(eTo.isEqualType(itemIsos.map(_.eTo)))

    override def equals(other: Any) = other match {
      case iso: StructsDsl#StructIso[_, _] =>
        (this eq iso) || (eFrom == iso.eFrom && eTo == iso.eTo)
      case _ => false
    }

    override def from(y: Rep[T]) = {
      val items = eFrom.fields.zip(eTo.fields).zip(itemIsos).map {
        case (((fnS, feS), (fnT, feT)), iso: Iso[s,t] @unchecked) =>
          fnS -> iso.from(y(fnT).asRep[t])
      }
      struct(items).asRep[S]
    }
    override def to(x: Rep[S]) = {
      val items = eFrom.fields.zip(eTo.fields).zip(itemIsos).map {
        case (((fnS, feS), (fnT, feT)), iso: Iso[s,t] @unchecked) =>
          fnT -> iso.to(x(fnS).asRep[s])
      }
      struct(items).asRep[T]
    }

    lazy val selfType = new ConcreteIsoElem[S, T, StructIso[S, T]](eFrom, eTo).asElem[IsoUR[S, T]]
  }

  def structIso[S <: Struct, T <: Struct](eFrom: StructElem[S], eTo: StructElem[T], itemIsos: Seq[Iso[_,_]]): Iso[S, T] =
    reifyObject(StructIso(eFrom, eTo, itemIsos))

  implicit class StructOps(s: Rep[Struct]) {
    def apply(iField: Int): Rep[_] = field(s, iField)
    def apply(fieldName: String): Rep[_] = field(s, fieldName)
    def getChar(fieldName: String): Rep[Char] = field(s, fieldName).asRep[Char]
    def getFloat(fieldName: String): Rep[Float] = field(s, fieldName).asRep[Float]
    def getDouble(fieldName: String): Rep[Double] = field(s, fieldName).asRep[Double]
    def getInt(fieldName: String): Rep[Int] = field(s, fieldName).asRep[Int]
    def getLong(fieldName: String): Rep[Long] = field(s, fieldName).asRep[Long]
    def getString(fieldName: String): Rep[String] = field(s, fieldName).asRep[String]
    def getBoolean(fieldName: String): Rep[Boolean] = field(s, fieldName).asRep[Boolean]
    def getByte(fieldName: String): Rep[Byte] = field(s, fieldName).asRep[Byte]
    def getUnit(fieldName: String): Rep[Unit] = field(s, fieldName).asRep[Unit]
    def getShort(fieldName: String): Rep[Short] = field(s, fieldName).asRep[Short]
  }

  def struct(fields: StructField*)(implicit o: Overloaded1): Rep[Struct] = struct(fields)
  def struct(fields: Seq[StructField]): Rep[Struct] = struct(defaultStructTag, fields)
  def struct[T <: Struct](tag: StructTag[T], fields: StructField*)(implicit o: Overloaded1): Rep[T] =
    struct(tag, fields)
  def struct[T <: Struct](tag: StructTag[T], fields: Seq[StructField]): Rep[T]
  def tupleStruct(items: Rep[_]*): Rep[Struct] = {
    val fields = items.zipWithIndex.map { case (f, i) => tupleFN(i + 1) -> f }
    struct(defaultStructTag, fields)
  }
  def field(struct: Rep[Struct], field: String): Rep[_]
  def updateField[S <: Struct](struct: Rep[S], fieldName: String, v: Rep[Any]): Rep[S]
  def field(struct: Rep[Struct], fieldIndex: Int): Rep[_] = field(struct, tupleFN(fieldIndex))
  def fields(struct: Rep[Struct], fields: Seq[String]): Rep[Struct]

  case class Link(field: String, nestedField: String, nestedElem: Elem[_], flatName: String)

  case class FlatteningIso[T <: Struct](eTo: StructElem[T], flatIsos: Map[String, Iso[_,_]], links: Seq[Link])
      extends IsoUR[Struct,T] {
    override def equals(other: Any) = other match {
      case iso: StructsDsl#FlatteningIso[_] =>
        (this eq iso) || (eFrom == iso.eFrom && eTo == iso.eTo)
      case _ => false
    }

    val eFrom = tupleStructElement(links.map(_.nestedElem): _*)
    lazy val selfType = new ConcreteIsoElem[Struct, T, FlatteningIso[T]](eFrom, eTo).asElem[IsoUR[Struct, T]]

    val groups = links.groupBy(_.field)

    def to(x: Rep[Struct]) = {
      val items = eTo.fields.map { case (fn, fe) =>
        val g = groups(fn)
        flatIsos.get(fn) match {
          case Some(iso: Iso[a, _] @unchecked) =>
            val projectedStruct = struct(g.map(link => (link.nestedField -> x(link.flatName))): _*)
            val s = iso.to(projectedStruct.asRep[a])
            (fn -> s)
          case _ =>
            assert(g.length == 1, s"Many fields $g can't relate to the single field $fn without iso")
            (fn -> x(g(0).flatName))
        }
      }
      struct(eTo.structTag, items: _*)
    }

    def from(y: Rep[T]) = {
      val items = eTo.fields.flatMap { case (fn, fe) =>
        val g = groups(fn)
        flatIsos.get(fn) match {
          case Some(iso: Iso[_, a] @unchecked) =>
            val nestedStruct = iso.from(y(fn).asRep[a]).asRep[Struct]
            // nestedStruct is guaranteed to be a Rep[Struct], because iso can be either IdentityIso on a struct or FlatteningIso
            g.map { link =>
              link.flatName -> nestedStruct(link.nestedField)
            }
          case _ =>
            List(g(0).flatName -> y(fn))
        }
      }
      struct(items: _*)
    }
  }

  /**
   * Flattens all subtrees of structs in [[e]].
   * Types other than structs are considered either as internal nodes or as leaves.
   * @param e descriptor of struct type
   * @return an isomorphism in which [[e]] is given by param and `eFrom` is flattened [[e]] preserving
   *         related order of the components
   */
  def getFlatteningIso[T](e: Elem[T]): Iso[_,T] = e match {
    // a == T, but Scala can't infer the type bound if T is used below
    case se: StructElem[a] @unchecked =>
      val flatIso = flatteningIso(se).asInstanceOf[Iso[_, T]]
      flatIso match {
        case Def(_: IdentityIso[T] @unchecked) =>
          flatIso
        case Def(_: FlatteningIso[T] @unchecked) =>
          flatIso.eFrom match {
            // TODO Actually, we currently know s == Struct. Is extra complexity needed?
            case eFrom: StructElem[s] =>
              val isos = eFrom.fields.map { case (fn,fe) => (fn, buildIso(fe, flatteningBuilder)) }
              val eFromNew = structElement(isos.map { case (fn, iso) => fn -> iso.eFrom })
              val sIso = reifyObject(new StructIso(eFromNew, eFrom, isos.map(_._2)))
              sIso >> flatIso.asInstanceOf[Iso[s,T]]
          }
      }
    case _ =>
      buildIso(e, flatteningBuilder)
  }

  val flatteningBuilder = new IsoBuilder { def apply[S](e: Elem[S]) = getFlatteningIso(e) }

  def flatteningIso[T <: Struct](eTo: StructElem[T]): Iso[_, T] = {
    val flatIsos: Map[String, Iso[_, _]] = eTo.fields.collect {
      case (fn, fe: StructElem[_]) => (fn, flatteningIso(fe))
    }.toMap

    if (flatIsos.isEmpty)
      return identityIso(eTo)

    // relate resulting field types by original field name
    val fromFields = eTo.fields.flatMap {
      case (fn, fe) =>
        flatIsos.get(fn) match {
          case Some(iso) =>
            iso.eFrom match {
              case flatElem: StructElem[_] =>
                flatElem.fields.map { case (nestedName, nestedE) => (fn, nestedName -> nestedE) }
              case _ => !!!(s"StructElem is expected as eFrom of flattened Iso $iso")
            }
          case None => List((fn, "" -> fe))
        }
    }

    val links =
      fromFields.zipWithIndex.map {
        case ((fn, (nestedN, nestedE)), i) => Link(fn, nestedN, nestedE, tupleFN(i + 1))
      }

    val res: Iso[_, T] = reifyObject(FlatteningIso(eTo, flatIsos, links))
    res
  }

  def getStructToPairsIso[T](implicit e: Elem[T]): Iso[_,T] = (e match {
    case pe: PairElem[a,b] =>
      val iso1 = getStructToPairsIso(pe.eFst)
      val iso2 = getStructToPairsIso(pe.eSnd)
      val res = structToPairIso(iso1, iso2)
      res
    case _ =>
      buildIso(e, new IsoBuilder {
        def apply[S](e: Elem[S]) = {
          getStructToPairsIso(e)
        }
      })
  }).asInstanceOf[Iso[_,T]]

  def getStructWrapperIso[T](implicit e: Elem[T]): Iso[_,T] = {
    getStructToPairsIso(e) match {
      case iso: Iso[s,T] @unchecked =>
        val flatIso = getFlatteningIso[s](iso.eFrom)
        flatIso >> iso
    }
  }

  case class MergeIso[T <: Struct](eTo: StructElem[T]) extends IsoUR[Struct,T] {
    override def equals(other: Any) = other match {
      case iso: MergeIso[_] =>
        (this eq iso) || (eFrom == iso.eFrom && eTo == iso.eTo)
      case _ => false
    }

    val eFrom = structElement(eTo.fields.flatMap { case (fn, fe: StructElem[_]) => fe.fields })

    lazy val selfType = new ConcreteIsoElem[Struct, T, MergeIso[T]](eFrom, eTo).asElem[IsoUR[Struct, T]]

    def to(x: Rep[Struct]) = {
      val items = eTo.fields.map { case (outerN, outerE: StructElem[_]) =>
        val s = struct(outerE.fields.map { case (innerN, innerE) => innerN -> x(innerN) })
        outerN -> s
      }
      struct(eTo.structTag, items: _*)
    }

    def from(y: Rep[T]) = {
      val items = eTo.fields.flatMap { case (outerN, outerE: StructElem[_]) =>
        val s = y(outerN)
        outerE.fields.map { case (innerN, innerE) => innerN -> s.asRep[Struct](innerN) }
      }
      struct(items: _*)
    }
  }

  def getStructMergeIso[T](implicit e: Elem[T]): Iso[_,T] = (e match {
    case se: StructElem[_] =>
      reifyObject(MergeIso(se.asElem[Struct]))
    case _ =>
      !!!(s"Don't know how merge non struct $e")
  }).asInstanceOf[Iso[_,T]]

  def tuplifyStruct[A <: Struct](se: Elem[A]): Elem[_] = {
    val res = foldRight[(String,Elem[_]), Elem[_]](se.fields)(_._2) { case ((fn,fe), e) => pairElement(fe, e) }
    res
  }

  def unzipMany[T](tuple: Rep[_], list: List[T]): List[Rep[_]] = {
    val pair = tuple.asRep[(Any, Any)]
    list match {
      case Nil => List(tuple)
      case x :: Nil => List(tuple)
      case x :: y :: Nil => List(pair._1, pair._2)
      case x :: xs =>
        pair._1 :: unzipMany(pair._2, xs)
    }
  }

  case class PairifyIso[A, AS <: Struct](eTo: Elem[AS]) extends IsoUR[A, AS] {
    val eFrom: Elem[A] = tuplifyStruct(eTo).asElem[A]

    def from(y: Rep[AS]) =  {
      val res = foldRight[String, Rep[_]](eTo.fieldNames)(fn => y(fn)) {
        case (fn, s) => Pair(y(fn), s)
      }
      res.asRep[A]
    }

    override def to(x: Rep[A]) = {
      val items = unzipMany(x, eTo.fields.toList)
      val fields = eTo.fieldNames.zip(items.map(_.asRep[Any]))
      struct(fields).asRep[AS]
    }

    override def equals(other: Any) = other match {
      case iso: PairifyIso[_,_] =>
        (this eq iso) || (eFrom == iso.eFrom && eTo == iso.eTo)
      case _ => false
    }
    lazy val selfType = new ConcreteIsoElem[A, AS, PairifyIso[A, AS]](eFrom, eTo).asElem[IsoUR[A, AS]]
  }

  def structWrapper[A:Elem,B:Elem](f: Rep[A => B]): Rep[Any => Any] = {
    val wrapperFun = (getStructWrapperIso[A], getStructWrapperIso[B]) match {
      case (inIso: Iso[a, A] @unchecked, outIso: Iso[b, B] @unchecked) =>
        outIso.fromFun << f << inIso.toFun
    }
    wrapperFun.asRep[Any => Any]
  }
  def structWrapperIn[A:Elem,B:Elem](f: Rep[A => B]): Rep[Any => B] = {
    val inIso = getStructWrapperIso[A]
    val wrapperFun = inIso.toFun >> f
    wrapperFun.asRep[Any => B]
  }
  def structWrapperOut[A:Elem,B:Elem](f: Rep[A => B]): Rep[A => Any] = {
    val outIso = getStructWrapperIso[B]
    val wrapperFun = f >> outIso.fromFun
    wrapperFun.asRep[A => Any]
  }

}

trait StructsDslStd extends StructsDsl with StructItemsDslStd with StructKeysDslStd { self: StructsDslStd with ScalanStd =>

  case class StructSeq[T <: Struct](tag: StructTag[T], fields: Seq[StructField]) extends Struct {
    override def equals(other: Any) = other match {
      case ss: StructsDslStd#StructSeq[_] =>
        tag == ss.tag && fields.sameElements(ss.fields)
      case p: Product =>
        val items = p.productIterator
        fields.iterator.map(_._2).sameElements(items)
      case _ => false
    }
    def findFieldIndex(fieldName: String): Int = fields.iterator.map(_._1).indexOf(fieldName)
  }

  def struct[T <: Struct](tag: StructTag[T], fields: Seq[StructField]): Rep[T] =
    StructSeq(tag, fields).asRep[T]
  def field(struct: Rep[Struct], field: String): Rep[_] =
    struct.asInstanceOf[StructSeq[_]].fields.find(_._1 == field) match {
      case Some((_, value)) => value
      case None => !!!(s"Field $field not found in structure $struct", struct)
    }

  def updateField[S <: Struct](struct: Rep[S], fieldName: String, v: Rep[Any]): Rep[S] = {
    val s = struct.asInstanceOf[StructSeq[S]]
    val buf = new scala.collection.mutable.ArrayBuffer[StructField](s.fields.length)
    s.fields.copyToBuffer(buf)
    val i = s.findFieldIndex(fieldName)
    buf(i) = (buf(i)._1, v)
    StructSeq(s.tag, buf).asInstanceOf[S]
  }

  def fields(struct: Rep[Struct], fields: Seq[String]): Rep[Struct] = {
    val StructSeq(tag, fieldsInStruct) = struct
    StructSeq(tag, fieldsInStruct.filter(fields.contains))
  }
}

trait StructsDslExp extends StructsDsl with Expressions with FunctionsExp with EffectsExp with ViewsDslExp with StructItemsDslExp
    with StructKeysDslExp with GraphVizExport { self: StructsDslExp with ScalanExp =>

  abstract class AbstractStruct[T <: Struct] extends Def[T] {
    def tag: StructTag[T]
    def fields: Seq[StructField]
    lazy val selfType = structElement(tag, fields.map { case (name, value) => (name, value.elem) })
  }

  // should this just extend BaseDef? Having field[T] would simplify usage in some cases
  abstract class AbstractField[T] extends Def[T] {
    def struct: Rep[Struct]
    def field: String
    lazy val selfType = Struct.getFieldElem(struct, field).asElem[T]
  }

  object Struct {
    def getFieldElem(struct: Rep[Struct], fn: String): Elem[_] = struct.elem match {
      case se: StructElem[_] =>
        se.get(fn).get
      case _ => !!!(s"Symbol with StructElem expected but found ${struct.elem}", struct)
    }

    def unapply[T <: Struct](d: Def[T]) = unapplyStruct(d)
  }

  def unapplyStruct[T <: Struct](d: Def[T]): Option[(StructTag[T], Seq[StructField])] = d match {
    case s: AbstractStruct[T] => Some((s.tag, s.fields))
    case _ => None
  }

  object Field {
    def unapply[T](d: Def[T]) = unapplyField(d)
  }

  def unapplyField[T](d: Def[T]): Option[(Rep[Struct], String)] = d match {
    case f: AbstractField[T] => Some((f.struct, f.field))
    case _ => None
  }

  case class SimpleStruct[T <: Struct](tag: StructTag[T], fields: Seq[StructField]) extends AbstractStruct[T]
  case class FieldApply[T](struct: Rep[Struct], field: String) extends AbstractField[T]

  case class FieldUpdate[S <: Struct, T](struct: Rep[S], fieldName: String, value: Rep[T]) extends AbstractStruct[S] {
    val tag = struct.elem.structTag
    val fields = struct.elem.fields.map { case (fn, _) =>
      if (fn == fieldName)
        (fieldName, value)
      else
        (fn, field(struct, fn))
    }
  }

  case class ProjectionStruct(struct: Rep[Struct], outFields: Seq[String]) extends AbstractStruct[Struct] {
    def tag = defaultStructTag
    val fields = outFields.map(fn => (fn, field(struct, fn)))
  }

  def struct[T <: Struct](tag: StructTag[T], fields: Seq[StructField]): Rep[T] = SimpleStruct(tag, fields)
  def field(struct: Rep[Struct], field: String): Rep[_] = FieldApply[Any](struct, field) // TODO Any?
  def updateField[S <: Struct](struct: Rep[S], fieldName: String, v: Rep[Any]): Rep[S] = FieldUpdate[S,Any](struct, fieldName, v)
  def fields(struct: Rep[Struct], fields: Seq[String]): Rep[Struct] = ProjectionStruct(struct, fields)

  override def syms(e: Any): List[Exp[Any]] = e match {
    case s: ProjectionStruct => syms(s.struct)
    case FieldUpdate(s, _, v) => syms(s) :+ v
    case s: AbstractStruct[_] => s.fields.flatMap(e => this.syms(e._2)).toList
    case _ => super.syms(e)
  }

  override def symsFreq(e: Any): List[(Exp[Any], Double)] = e match {
    case s: ProjectionStruct => symsFreq(s.struct)
    case s: AbstractStruct[_] => s.fields.flatMap(e => symsFreq(e._2)).toList
    case _ => super.symsFreq(e)
  }

  override def effectSyms(e: Any): List[Exp[Any]] = e match {
    case s: ProjectionStruct => effectSyms(s.struct)
    case s: AbstractStruct[_] => s.fields.flatMap(e => effectSyms(e._2)).toList
    case _ => super.effectSyms(e)
  }

  override def readSyms(e: Any): List[Exp[Any]] = e match {
    case s: AbstractStruct[_] => Nil //struct creation doesn't de-reference any of its inputs
    case _ => super.readSyms(e)
  }

  override def aliasSyms(e: Any): List[Exp[Any]] = e match {
    case SimpleStruct(tag,fields) => Nil
    case FieldUpdate(s, fn, v) => Nil
    case FieldApply(s,x) => Nil
    case _ => super.aliasSyms(e)
  }

  override def containSyms(e: Any): List[Exp[Any]] = e match {
    case SimpleStruct(tag,fields) => fields.collect { case (k, v: Exp[_]) => v }.toList
    case FieldUpdate(s, fn, v) => List(v)
    case FieldApply(s,x) => Nil
    case _ => super.containSyms(e)
  }

  override def extractSyms(e: Any): List[Exp[Any]] = e match {
    case SimpleStruct(tag,fields) => Nil
    case FieldUpdate(_,_,_) => Nil
    case FieldApply(s,x) => syms(s)
    case _ => super.extractSyms(e)
  }

  override def copySyms(e: Any): List[Exp[Any]] = e match {
    case SimpleStruct(tag,fields) => Nil
    case FieldUpdate(_,_,_) => Nil
    case FieldApply(s,x) => Nil
    case _ => super.copySyms(e)
  }

  override protected def formatDef(d: Def[_])(implicit config: GraphVizConfig): String = d match {
    case SimpleStruct(tag, fields) =>
      s"${baseStructName(tag)}{${fields.map { case (fn, s) => s"$fn:$s" }.mkString("; ")}}"
    case ProjectionStruct(struct, outs) => s"$struct.{${outs.mkString(",")}}"
    case FieldUpdate(s, fn, v) => s"$s.$fn := $v"
    case FieldApply(struct, fn) => s"$struct.$fn"
    case _ => super.formatDef(d)
  }

  case class ViewStruct[A, B](source: Exp[A])(val iso: Iso[A, B])
    extends View[A, B] {
    override def toString = s"ViewStruct[${iso.eTo.name}]($source)"
    override def equals(other: Any) = other match {
      case v: ViewStruct[_, _] => source == v.source && iso.eTo == v.iso.eTo
      case _ => false
    }
  }

  override def unapplyViews[T](s: Exp[T]): Option[Unpacked[T]] = (s match {
    case Def(view: ViewStruct[a, b]) =>
      Some((view.source, view.iso))
    case _ =>
      super.unapplyViews(s)
  }).asInstanceOf[Option[Unpacked[T]]]

  object FieldGet {
    def unapply[T](d: FieldApply[T]): Option[Exp[T]] = d match {
      case FieldApply(Def(SimpleStruct(_, fs)), fn) =>
        val optItem = fs.find { case (n, _) => n == fn }
        optItem.map(_._2.asRep[T])
      case _ => None
    }
  }

  object IdentityStructMapping {
    def unapply[A](d: Def[A]): Option[Rep[A]] = d match {
      case Struct(_, fields) =>
        val inputStructs = scala.collection.mutable.HashSet[Rep[A]]()
        val okNames = fields.forall { case (fn, s) =>
          s match {
            case Def(Field(struct, name)) if name == fn =>
              inputStructs += struct.asRep[A]
              true
            case _ => false
          }
        }
        if (okNames && inputStructs.size == 1)
          Some(inputStructs.head)
        else
          None
      case _ => None
    }
  }

  object IdentityStructLambda {
    def unapply[A,B](lam: Lambda[A, B]): Boolean = lam.y match {
      case Def(Struct(_, fields)) =>
        fields.forall { case (fn, s) =>
          s match {
            case Def(Field(struct, name)) if struct == lam.x && name == fn => true
            case _ => false
          }
        }
      case _ => false
    }
  }

  override def isIdentityLambda[A,B](lam: Lambda[A, B]): Boolean = {
    super.isIdentityLambda(lam) || IdentityStructLambda.unapply(lam)
  }

  def shouldUnpackTuples = currentPass.config.shouldUnpackTuples
  def shouldExtractFields = currentPass.config.shouldExtractFields
  def shouldSlice = currentPass.config.shouldSlice

  override def rewriteDef[T](d: Def[T]): Exp[_] = d match {
    case FieldGet(v) if shouldExtractFields => v
    case IdentityStructMapping(s) => s
    case _ => super.rewriteDef(d)
  }

  object StructsRewriter extends Rewriter {
    def apply[T](x: Exp[T]): Exp[T] = (x match {
      case Def(FieldGet(v)) => v
      case _ => x
    }).asRep[T]
  }
}


This is what happens when you treat Jamaican Rum like a fine, single malt Whiskey … and it mighty good, mon!
This Rum is all about the blush, and Appleton Estate 21-year has got it all! You see, when fine Rums are aged properly in premium barrels, sure they get darker and richer in color. But in addition to the golden amber hues taken on my most aged spirits, fine Rum takes on a reddish hue as well. And the pallet mellows out into a rich, viscous, flavor explosion. Its complex character will surprise you. Do not feel bad if you are fooled at first, thinking that you are having a fine, sweet Scotch or Cognac at first sip. Let it settle in and you will recognize all the Rum coming through.
When Uncle Flaviar took his first sip, he grew out his dreads, pulled up his kilt, issued forth such a sigh of satisfaction as we have not heard in a very long time, and immediately dropped to one knee to proposed marriage to the Master Blender, Joy Spence. She politely declined and poured him another round on the house.
What does Appleton Estate Rum 21 Year Old taste like?
The Flavor Spiral™ shows the most common flavors that you'll taste in Appleton Estate Rum 21 Year Old and gives you a chance to have a taste of it before actually tasting it.
The best Appleton there is.
A good rum, definitely snifter or on the rocks class. I (gasp) mixed it and it was delightful, definite difference. Just cant bring myself to use this kind of quality in a mixed drink. PS. Not a big fan of rums normally.
Favorite rum so far. Snifter glass a must. On the rocks for my taste.
My go to drink when I just need to kick back and relax.


text:
Office for the Prevention of Hate Crimes311 Search all NYC.gov websites
Text-Size
SelectAbout Hate CrimesFrequently Asked QuestionsInformation on Hate SymbolsVictim SupportYouth and EducationReports and Statistics
About Hate Crimes
Information on Hate Symbols
OPHC understands that hate is learned, but it can also be unlearned. By prioritizing education initiatives and the creation of curricular resources for youth, OPHC has engaged in long-term approaches to preventing hate crimes in New York City through:
HeARTwork Against Hate Contest
Heroes Against Hate
Youth Leadership Council Against Hate
OPHC Hate Crime Curriculum
The HeARTwork Against Hate is a creative initiative for New York City youth launched by the Office for the Prevention of Hate Crimes in September 2020.
It is important to support young New Yorkers at a time of great stress resulting from the combination of a global pandemic, economic uncertainty, school changes, scapegoating, and issues of systemic racism that have come to the fore. HeARTwork Against Hate is an opportunity and a platform for young New Yorkers to use artistic expression as an outlet.
Learn more about HeARTwork Against Hate
The NYC Department of Youth and Community Development (DYCD) in partnership with NYC-based comic book artist Michael O'Shea, created the Comic Book Project, and, in partnership with OPHC, focused the 2020 project on the theme, "Heroes Against Hate."
The comic book tells the story of young New Yorkers joining forces with "Nurse Healthy" to battle the villain "Mr. No Mask" to bring New Yorkers together against hate, discrimination, and harassment.
View the "Heroes Against Hate" comic book
The OPHC joined the NYC Youth Leadership Councils (YLCs) organized by NYC Service & Generation NYC to form its own Youth Leadership Council Against Hate (YLCAH). The YLCs are a network of youth groups focused on policy, practice, and advocacy to make local change happen—each YLC is a space to team up with others, share ideas, create solutions, and put those solutions into action with support from City agencies, schools, and community organizations.
The OPHC invited youth leaders (grades 9-12) from New York City schools to serve as advisors on the development of a hate crime curriculum. In this new initiative, the Youth Leadership Council Against Hate (YLCAH) provides close feedback on the curriculum, as well as provides input on other issues highlighted by the OPHC, including restorative justice, victim services, education resources, and strategies to enhance incident reporting. YLCAH members learn skills to be upstanders against hate, providing their peers with educational resources on how to prevent and respond to hate crimes and bias incidents in their own schools.
If you are interested in learning more about OPHC's YLC, email OPHCEducation@cityhall.nyc.gov.
Required by New York City Council local law to create anti-hate curricular resources in consultation with the NYC Department of Education, the OPHC interpreted this mandate broadly, designing in-house a comprehensive curriculum for all NYC middle- and high-school students. Seizing an opportunity during the COVID-19 pandemic to create a curriculum adaptable to a variety of settings, the curriculum will be both fully online and designed for both remote and in-person teaching.
If you would be interested in introducing the OPHC Hate Crimes Curriculum in your school or have any other inquiries regarding our curriculum, please connect with us at OPHCEducation@cityhall.nyc.gov.
Directory of City Agencies Contact NYC Government City Employees Notify NYC CityStore Stay Connected NYC Mobile Apps Maps Resident Toolkit
City of New York. 2022 All Rights Reserved,
NYC is a trademark and service mark of the City of New York

redpajama_set_name: RedPajamaCommonCrawl


text:
AfDB holds virtual meetings 25-27 August; election of president key on agenda
The African Development Bank (AfDB) Group will hold its 2020 Annual Meetings virtually, from 25-27 August 2020.
These will comprise statutory meetings of the Board of Governors.
According to the bank, a major agenda item of this year's annual meetings will be the election of a president.
Meanwhile, the Board of Directors of the African Development Fund (ADF) on last month approved a $69 million grant to support Ghana's efforts to tackle the COVID-19 pandemic and mitigate its socio-economic impact on the nation.
The grant from the ADF, the concessional arm of the African Development Bank, will provide fiscal budget support to finance the government's national COVID-19 Emergency Preparedness and Response Plan, and Coronavirus Alleviation Program.
Specifically, the funds will help to upgrade the capacity of healthcare facilities to isolate, diagnose and care for patients, and provide more test kits, pharmaceuticals, equipment and beds. It will also ensure adequate personal protective equipment (PPE) for health workers and support financial incentives and an insurance package for health and allied professionals.
Ghana ranks fourth in COVID-19 infections in Africa after South Africa, Egypt and Nigeria.
As of 9 August 2020, the West African nation had recorded 41,003 cases of the disease, with 38, 330 recoveries and 215 deaths.
"Overall, the objective is to help contain the spread of the virus, expand testing and ease the impact of the virus on social and economic life, through measures aimed at protecting jobs, sustaining livelihoods and supporting small businesses," said Marie-Laure Akin-Olugbade, the Bank's Director General for West Africa.
The ADF grant is a Crisis Response Budget Support operation, disbursable in a single tranche under the Bank's $10 billion COVID-19 Response Facility.
Under Ghana's COVID-19 response program, all affected persons will receive free treatment and free water supply. Micro, Small and Medium enterprises (MSMEs) will benefit from a soft loan scheme with one-year moratorium and two-year repayment period. The private sector will also benefit from a tax freeze and refund, direct subsidies and a guarantee fund, enabling businesses to access bank credit.
The program also aims to increase the percentage of the population tested from one percent to three percent by the end of December 2020, boost the number of points of entry reporting suspected cases of COVID-19 from 1 to 14 by the end of September 2020, and increase designated treatment centers with adequate intensive care facilities to 100% by end December 2020.
Eminent economists to prioritise best policies for Ghana's future
CMS: GCB donates GHS100K to UW Health Directorate
Ghana spent GH₵12.748bn to import rice, fish, chicken between 2017 and 2020
Dec 17, 2021 Felix Adinkra
Fuel price to fall by 3 to 5% as year ends – IES
Make chiefs signatories to mining concessions – Otumfuo


As a family practice, we deal with all age groups. Our featured services include adult physical, children physical, well baby care, vaccinations, preventative medicine, family planning, women's health, chronic disease management, and more.
We strive to make our office a comfortable environment where you can be rest assured that you will leave us with a better health plan for your lifestyle.
Patients must present a valid health card each time you visit the clinic.
Please inform our receptionists of any changes in your address or phone number. This is extremely important to ensure proper communication in case of abnormal investigation.
Patients are responsible for payment, if you do not have a valid Health Card.
Not all services are covered by OHIP. Please see our list of services with fees.
Family practice patients (patients who are registered with one of our doctors) are encouraged to book an appointment as the wait time will be significantly less.
Our Walk In Clinic is open 7 days a week for urgent and minor care needs. No appointment necessary.
Please try to arrive at least one hour before closing to guarantee being seen, as we sometimes have to close registration early due to patient overload (walk in patients only).
For after hours health advise, please call TELEHEALTH ONTARIO.


text:
<!DOCTYPE html>

		<meta charset="utf-8">
		<title>Projects</title>
		<link rel="icon" href="../images/favicon.ico">
		<link rel="shortcut icon" href="../images/favicon.ico">
		<link rel="stylesheet" href="../css/touchTouch.css">
		<link rel="stylesheet" href="../css/style.css">

							Menu

首页

博雅简介

服务内容

案例

团队成员

联系我们

More Website Templates - February 24, 2014!

Our Projects

Hom dui erosi laoru adip

						In mollis erat mattisy nequelisis sit amet ultricieser erarutrum. Cras facilisis, nulla vel viverra

						more

Vivamus at magna non

						Fermollis erat mattisy nequelisis, sit amet ultricieser erarutrum. Cras facilisis, nulla vel viverra

						more

Curabitur vel lorem sit

						In mollis erat mattisy nequelisis, sit amet ultricieser erarutrum. Cras facilisis, nulla vel viverra

						more

Phasellus erat nisuctor

						Hhol mollis erat mattisy kilomi nequelisis, sit amet ultricieser erarutrum. Cras facilisisolo

						more

Etiam dui eros, laoreet

						Mollis erat mattisy nequelisis, sit amet ultricieser erarutrum. Cras facilisis, nulla vel viverra aucto

						more

Dui eroslaoreetdui ero

						In mollis erat mattisy nequelisis, sit amet ultricieser erarutrum. Cras facilisis, nulla vel viverra

						more

A at magna noru adip

						Hlottisy nequelisis, sit ametyter ultricieser erarutrum. Crasyto facilisis, nulla vel viverra auc

						more

Retui erosi laoru adip

						Koliu erat mattisy nequelisis, sit amet ultricieser erarutrum. Cras facilisis, nulla vel viverra auctom

						more

						BizGroup © 2014 | Privacy Policy

redpajama_set_name: RedPajamaGithub


When we moved here, one of the things I dreaded was making friends. They're such an overhead of time and money: the phone calls, the constant demands for reassurance, the endless thoughtful birthday presents (I mean how many birthdays can one person have?), the three hour lunches . . .
I meant to say: I dreaded the process of MEETING people.
The circle of friends we had in Dubai were in many ways the closest thing we had to family. I miss them every day. Now we have to start all over again.
Making friends gets harder as you get older. You look for deeper qualities than an extensive wardrobe to pilfer borrow from, your boyfriends being best mates, a frothy sense of humour, or whether someone will talk to you. Admittedly, I am still drawn to people who talk to me; but these days I prefer a sense of humour that's crisp and refreshingly dry. As for our partners being best friends? Well, all that indicates is both of us has dubious taste.
Now, with benefit of hindsight and a dash of maturity, I know it takes years. The potential of a new relationship sparkles, but nothing surpasses the lustre of an enduring friendship.
Of course, the effort is worth it. It's just . . . well . . . why can't friends just spring into your life fully formed? How long does it take to learn the in-jokes, for goodness' sake? If you trust me, I'll trust you. There. Any freaky character traits you want to share? No, me neither.
I was flattered by the number of people who assumed Husband and I would have no problem Making Friends, that there would be so many hopeful applicants we would have to hold auditions every Wednesday and beat them off with a stick.
The only thing we've been beating off is mosquitoes.
Much of this has to do with where we've chosen to live. We will move to South Island within two years, so there is not the same imperative to meet people. Socialising is complicated by a half hour drive to civilisation and Husband working evenings.
My first attempt at procuring a friend was an abject failure. At the Christopher Howard Seminar, I met John and Yvette. Many of the attendants I sincerely hoped I'd never come across again – especially if I were alone and unarmed – but John and Yvette were different.
For a start, John's 'cynic shield' (as one woman described my attitude) rivalled mine. He refused to partake in the hyper high-fiving, so I high-fived Yvette across him and occasionally high-fived the upside of his head when he wasn't getting the message.
Afterwards, Yvette asked for my phone number and we exchanged contact details.
For the rest of the week, I seized upon every opportunity – and even made up a few – to remind Husband about MY FRIEND and how great she was and how I was really looking forward to lunch.
The day before lunch, Yvette called to say she couldn't make it for a reason which, at the time, sounded entirely genuine (washing her cat).
"What's up?" said Husband as I mooched around the living room moodily dodging advancing dust bunnies.
During the week, my self-confidence returned and I promoted Yvette from Erfriend back to My Friend. I also stepped up the guerrilla tactics, sneaking up on Husband unawares and shouting: "My friend!" into his ear.
I'm sure you can see exactly where this is going.
Yes. She cancelled again (Christmas shopping).
The compassion is all part of his long-term devious scheme to drive me over the edge.
"Maybe you should advertise for a friend on Trademe," he suggested.
In the end, we didn't have to. Last time we were in South Island, we learned that Husband's college mate's brother lives just down the road from us (that being about 8km).
The first time we met MarkJ, we went around to his place. We wondered whether we had got the right house – the entire place was dark – but rang the doorbell anyway. There was a bang, followed by a mechanical hum; then the garage door groaned up and it was like that scene in ET – you know where the aliens stop by to pick up ET and you wonder what's going to come out of the spacecraft?
When the garage door opened fully it was still pitch black, and I don't know about Husband but I was holding my breath. Then the light blared on and there was MarkJ perfectly framed in the doorway.
It was possibly the most dramatic greeting I've ever experienced. Subsequent meetings can only suffer in comparison, but each has been full of chat, frequently entertaining, and often freaky. MarkJ is a multi-talented, all-purpose friend: he can conduct simultaneous conversations with Husband about cars while discoursing the nature of solitude with me. We will see much more of him.
So we did. Husband got bored around the two hour point and went to – ok, I'm not sure where because I didn't notice him leave – but Shelley and I talked for another hour and a half and could have kept going.
Last weekend, we met her husband Greg who is almost as nice (Shelley's Irish. It's an unfair advantage, I know), and daughter Victoria. They are an awesome family.
And finally, can we claim John and Haze as new friends? John is less grumpy having left Dubai, and Haze less dusty, so it's almost like they're different people.


text:
Fox Killed After Attacking Woman In Bowdoinham
Maine Public | By Associated Press
Published May 9, 2019 at 12:01 PM EDT
BOWDOINHAM, Maine - Officials say a fox bit a woman outside her home in Bowdoinham, Maine, then chased a neighbor's dogs before running into the neighbor's house, where it was killed. Sagadahoc Chief Deputy Brett Strout said the neighbor managed to pin the fox to the floor while his son killed it with a shovel on Tuesday.
The Bangor Daily News reports that seven animals in Sagadahoc County have tested positive for rabies since February. The Maine Center for Disease Control and Prevention said four of them were in the city of Bath, and one each in Bowdoin and Bowdoinham.
Animal Control Officer Cliff Daigle said the dead fox in Tuesday's incident had porcupine quills embedded in it. The fox is being tested for rabies at the state Health and Environmental Testing lab.
Healthfoxrabies


Swift Brick Repair will be available for your goals involving Brick Repair in Auriesville, NY. Our team of experienced experts will give you the service you need with the most sophisticated technology available. We use high quality materials and money conserving strategies to ensure that you get the right products and services for the best price. Contact us today at 844-222-4922 and we will be able to discuss your options, resolve your concerns, and organize an appointment to commence setting up your project.
Here at Swift Brick Repair, we are aware that you'll want to stay within your financial budget and lower your costs anywhere you are able to. On the other hand, you will want the absolute best and finest quality of work when it comes to Brick Repair in Auriesville, NY. We provide you with the finest quality while saving you money. We utilize the best strategies and supplies to make sure that any task can tolerate the years, and we save some costs in ways that won't affect the excellent quality of your work. We will accomplish this by giving you the very best bargains around and avoiding expensive complications. Call Swift Brick Repair when you'd like the most impressive service at a minimal cost. You can communicate with our team by dialing 844-222-4922 to start out.
Brick Repair are available in Auriesville, NY.
You have to be well informed concerning Brick Repair in Auriesville, NY. You should not go into it without consideration, and you will need to learn what to expect. We will take the surprises out of the scenario through providing appropriate and detailed advice. The first step is to call us at 844-222-4922 to begin your work. With this phone call, you'll get the questions you have answered, and we'll establish a time to start the work. Our company is going to arrive at the scheduled time with all the required supplies, and will work together with you during the entire process.
Lots of good reasons exist to pick Swift Brick Repair for Brick Repair in Auriesville, NY. We have the greatest customer care ratings, the very best quality supplies, and the most effective and productive money saving strategies. We fully understand your expectations and intentions, and we're there to serve you using our expertise. If you want Brick Repair in Auriesville, contact Swift Brick Repair by dialing 844-222-4922, and we will be beyond happy to help.


text:
Common name: Hornwort;
Botanical name: Ceratophyllum demersum
Management programme: Exclusion, Eradication, Progressive Containment
Hornwort is currently considered New Zealand's worst submerged weed. Also known as coon tail; the tip of the plant is thick and looks similar to the tip of a racoon's tail. The free floating mats of hornwort have been known to have blocked hydro-electric dams in the past.
Grows up to 10m - much taller than other weed species.
It can survive as a free-floating mat, absorbing all the nutrients it needs from the surrounding waters.
Free floating mats of hornwort can grow to such large sizes that they completely shade out entire areas of lakes, inhibiting growth of native flora and fauna. Shallow lakes such as Lake Rotoehu are prime candidates for such exponential growth.
It is found in lakes, ponds, marshes, and slow flowing streams.
Hornwort does not set seed in New Zealand, but reproduces from broken-off fragments that are easily moved to new sites via water movement and strong winds. Fragments also hitch rides on boats, trailers, nets and fishing gear.
As at 2020, present in lakes Rotorua, Tarawera, Rotoiti, Ōkataina, Rotoehu, Ōkāreka and Rotomahana.
Hornwort is a submerged freshwater perennial aquatic plant that may occur as stems attached to the sediment or as a floating mat or drifting fragments.
It has a very delicate appearance as the stems are thin and break easily through wave action.
Whorled branched, narrow leaves, rough to the touch and densely crowded at the tip and sparse at the base.
Narrow, bright green leaves 4cm long and finely divided.
It does not have roots but may be anchored to the sediment by the base of its stems.
The flowers are tiny (2mm long) in the leaf bases. Flowers are present November to March and are a white, pink, or greenish colour.
Exclusion pests are not known to be present or established in the Bay of Plenty region. The Bay of Plenty Regional Council is responsible for managing new incursions into the region. Action may be required from landowners or occupiers to support a control operation.
Eradication pests are present in the region but are limited in their size or extent of infestation. The eradication of these organisms is a feasible and cost-effective solution. The Bay of Plenty Regional Council is responsible for their control or eradication from the region. Action may be required from landowners or occupiers to support a control operation.
Progressive Containment species are pests which the Council aims to prevent from spreading, reduce the distribution, or eradicate within parts of the region over time. Landowners or occupiers are responsible for the control of Progressive Containment species on their property. Council may enforce the control of these pest species.
We are trying to prevent hornwort from getting into our waterways which have not been infested. If you are travelling with equipment or machinery between waterways please ensure that you check, clean, and dry.
If you would like advice on how to control hornwort please contact the Bay of Plenty Regional Council.
Management programme map


text:
You are at:Home » Football » Nottm Forest v Millwall: Forest fancied to keep Lions at bay
Nottm Forest v Millwall: Forest fancied to keep Lions at bay
By James O'Rourke on	 Feb 5, 2020 Football, Football League Tips, Tips
CHAMPIONSHIP specialist James O'Rourke (@JamesOR1) shares his thoughts on Friday night's match-up between Nottingham Forest and Millwall.
Nottingham Forest v Millwall | Friday 6th March 2020, 19:45 | Sky Sports
Your Friday night viewing comes from the Championship this weekend as promotion hopefuls Nottingham Forest entertain a Millwall side looking to close the gap to the play-off positions. Neither team are in blistering form of late in terms of victories, but they continue to prove hard to beat. Therefore, quite a tight and tactical contest is anticipated at The City Ground.
A reason for this is because Millwall have a joint-league high of 15 draws to their name. They've lost only nine of 36 matches, which is only one less than Forest, yet there is a nine point difference. There is very little in comparison in terms of goals scored and conceded, so it really is likely to be a case of fine margins determining this one.
Lamouchi demands Forest response
It was a funny old night at the Riverside Stadium on Monday night. Forest took the lead early on, to then fall behind before half-time and then earn a last gasp equaliser to earn an away point. Boss Sabri Lamouchi said in the end he was relieved with a draw, but overall was disappointed with their performance, highlighting their lack of organisation as a particular issue.
Strong organisation has ultimately been the bedrock to their improved showing this season, so that will be a bit of a concern. Nevertheless, an away draw is never necessarily a bad thing, and they're normally good at bouncing back when the question is asked of them.
Whilst automatic promotion may appear a little out of reach at the moment, Forest do still need to keep the foot on the accelerator. A few defeats could then all of a sudden see their play-off spot come under threat, with a team like Millwall hoping to pounce.
Patience may be key however as Forest are used to teams coming to the City Ground and playing a particular way. They've dropped home points to the likes of Middlesbrough, Charlton, Hull and Reading.
Rowett calls for stronger start
Gary Rowett was another manager not best pleased with how side team performed last time out. They hosted an out of sorts Bristol City, and the Millwall boss was rather annoyed with how they started the match. They fell behind after 10 minutes, and following the encounter he stated his unhappiness with the first 20 minutes and felt it was a missed opportunity.
A trip to Nottingham Forest therefore is another presented opportunity for them, and the sort of one they really need to make the most of if they're to really gate-crash the promotion picture. That is easier said than done of course, but the Lions have notable away scalps of Preston, Bristol City, Swansea and Derby to their name this season, so they're capable.
The concern at the moment is that goals are proving quite hard to come by. It is just three across their last seven league fixtures, and with that being the case you can safely assume that Rowett will set his team up in a relatively defensive manner and look to play on the counter attack.
Playing this 3-4-3 shape away from home has proved quite successful, and tactically it may suit against a Forest side who have issues against such shapes.
The betting angle
One difference between these teams is that Forest generally carry a greater goal threat in relation to having more shots on goal. They sit sixth in the league average for shots on goal, whilst Millwall are all the way down in 20th. That is why I do think Forest are the side we really have to focus on, but also acknowledge that Millwall will come looking to make life hard for their opponents.
The reality is that is two wins in seven for Forest, but three of the last four have been draws. It is one triumph in nine for Millwall, with four of the last seven being draws. Neither are at the peak of their powers at all.
It is noticeable that goals don't tend to flow at the City Ground, mainly because of reasons I have stated above. 11 of 17 here featured Under 2.5 Goals, including the last four. Millwall's last seven in succession ended under, too, so they're not unfamiliar to these type of matches.
Nottingham Forest Double Chance and Under 2.5 Goals is a worthy 23/20 (Betway) call.
Nottingham Forest v Millwall – Nottingham Forest Double Chance and Under 2.5 Goals (23/20 Betway)


Ear correction surgery or a Pinnaplasty operation, corrects protruding or imbalanced ears, or ears that are out of proportion with other facial features.
The surgery can be performed under a local anaesthetic or general anaesthetic and usually takes about an hour. Small incisions are made in the natural crease of the ear, through which the surgeon re-shapes the cartilage and in some cases a small portion is removed. The ear is then stitched back into place in the correct position. The patient's ears will be packed with moulding material and your head will be bandaged.
Pinnaplasty is a relatively quick operation and patients are able to go home the same day. Patients should plan to take a week off from work any strenuous work or activity should be avoided for at least four weeks.
For a week following surgery it will be necessary for the patient to wear bandages around their ears, and smaller bandages for a few weeks after that to ensure the natural healing process happens as quickly and effectively as possible. The patient will then need to return to the clinic to have their head dressing and any stitches removed.
Discomfort – Some pain is common with most operations, but the patient will be prescribed painkillers for a few days following surgery.
Bleeding – Bleeding can occur after surgery but is easily managed by the surgeon.
Scarring – In certain cases scarring of the skin can occur but this will fade over time and is hidden behind the ear.


Discolored teeth can be debilitating. They can damage your self-esteem and inhibit you from showing a true smile. Rather than avoiding your discolored teeth, ask us about the advantages of Zoom Whitening. This simple and painless cosmetic dentistry procedure can be done at Crafton Dental. What could be better than receiving a brighter, whiter smile?
Zoom Whitening is done in the Columbia MD office with a whitening gel that is applied to your teeth while the rest of your mouth, including your gums and lips, is isolated. The gel is then activated with the use of a special light that then bleaches your teeth — giving you that bright, white smile that you desire. There is zero discomfort and no recovery period required to give you the "pearly whites" you deserve.


Like a personal assistant, but better.
With the largest travel network in the industry, you can explore your city, find its hidden hotspots, and map out memories as you book activities world-wide. Download the app for iOS or Android for free.
We get it, you don't want just "another-city-guide" app. You want quality. You want to know about best of the best, you want to book activities for that romantic gateway for two you've been planning for weeks now. You want that last minute birthday gift because you completely forgot about it. We get it, and our team has worked hard to handpick and present a select list of high-end merchant solutions for you - our VIP!
What's that? Can we deliver that gift to your house? Yes, you bet we can!
Who wants to waste time waiting in any lines? We get it, you have a busy life and spending time waiting in line is not your thing. You're craving that sushi the whole day, aren't you? How about that t-shirt you wanted forever but the lineup is just too long... No worries, we've got you covered.
Specifically designed & implemented for concierge teams that want a streamlined digital connection with their guests. Join us from anywhere around the world and earn by promoting personalized experience to your guests.
mobiSIM card works in 37 cities around the world. Need data on the go? Check - customize your package to what makes sense to you, data included. Donwload the app and get your mobiSIM card today!


Need an experienced Appliance Repairman? Don't just call an average Appliance Repairman, call a local Appliance Repair Store. Our mission is to provide expertise, reliable and affordable Appliance Repair Shop in Nettleton. We have established ourselves as a leader in the industry in pursuit of that goal. Call (877) 691-7659 for Affordable Appliance Repair Service.
Our Nettleton Appliance Repair Technicians have years of Appliance Repair experience and have seen just about every problem. Several of our Technicians have 20+ years on the job and have been fixing washers and dryers, dishwashers, and refrigerators since we first opened.
Appliance Repair Nettleton (877) 691-7659, is ready and able to fix or correct your appliance problem at very affordable prices. Our Appliance Repair training and experience have not only made us leaders, but experts in the Appliance Repair Service Industry. Being a manufacturer authorized Service Center in the Nettleton area enables us to service most major appliance brands new and old.
With just one (1) washer dryer repair service call, you will probably find out what's wrong with your appliance from one of our skilled washer dryer repair technicians and get a washer dryer repair cost estimate. We service the complete Nettleton MS area and most towns close to Nettleton at very reasonable and affordable cost.
Call us now for our in-home appliance repair service in Nettleton. We can be reached at (877) 691-7659, for appliance service in your home within a 72-hour period (allowing for weekends) or for same day services in Nettleton call for availability.
This entry was posted in Mississippi and tagged All Brands Appliance Repair Nettleton Mississippi, Appliance Repair Near Me Nettleton Mississippi, Appliance Repair Service Nettleton Mississippi, Appliance Repair Shop Nettleton Mississippi, Appliance Repair Store Nettleton Mississippi, Dishwasher Repair Nettleton Mississippi, Dishwasher Repair Service Nettleton Mississippi, Dryer Repair Nettleton Mississippi 38858, Freezer Repair Nettleton Mississippi 38858, Fridge Repair Service Nettleton Mississippi 38858, Refrigerator Repair Nettleton Mississippi, Refrigerator Repair Service Nettleton Mississippi, Refrigerator Service Nettleton Mississippi, Washer & Dryer Repair Service Nettleton Mississippi, Washer And Dryer Repair Service Nettleton Mississippi, Washer Repair Nettleton Mississippi 38858, Washer Repair Service Nettleton Mississippi, Washing Machine Repair Nettleton Mississippi, Washing Machine Repair Service Nettleton Mississippi, Washing Machine Service Nettleton Mississippi. Bookmark the permalink.


Convincing people to help an often demonized predator isn't easy, but that's just what 2015 National Geographic Emerging Explorer Jessica Cramp left her career and home to do. Cramp helped establish a shark sanctuary in the Cook Islands and is showing local fishermen and others why these creatures are so important to our oceanic ecosystems.
Shark populations are being declined faster than we can count. And these numbers are adding up to like over a hundred million sharks per year are dying they say, just for their fins.
Thank you for allowing me to speak to a group of supporters on sharks because that is not always my situation. Four years ago, I had a decision to make. And I learned about this tiny group called the Pacific Islands Conservation Initiative in the Cook Islands. The founder of that initiative had a dream. His name is Steve Lyon and he wanted to create a shark sanctuary. I couldn't even find this country on a map three weeks prior. But I decided to jump on board to help make his dream a reality. Our campaign was as grassroots as it gets. We used handheld cameras and found local ambassadors. And we tried to create a roadmap of local people that we could teach about sharks that could then go out into the community and talk about it.
We talked to mamas and papas, we talked to school children we talked to farmers, to voyagers and to fishermen. We started getting quite a bit of support from the community. From places that we expected, from the children. But also from some places we didn't expect like from commercial fishermen. We also received support when we weren't looking. There were times where we would be on outer islands meeting one on one with mayors, barefeet under coconut trees where we would discuss the regulations with them. The regulations that we were proposing, which in short we weren't taking away the rights of the local fishermen. So, if the local fishermen were to catch a shark they would be allowed to bring it ashore and eat it. That was common, there was a culture in the Cook Islands. We weren't trying to take that away. Because we were transparent and working with local people and asking their opinions, we garnered their trust as well. And while we were on these outer islands, a bank decided to use a local rubbish sculpture competition to show their support for sharks. You notice they put their fin on the head. This is what you do when you see a shark in the wild underwater. Sometimes I'm like mmmmmm! But usually this works a bit better. we used around the campaign to show universal support for shark protection.
Um, she was affectionately referred to as Aunty Hillary in the Cook Islands. She still has a doughnut and a smoothie named after her. And she doesn't realize it but this tiny gesture made a bit of a difference politically, because if Aunty Hillary was down in the Cook Islands showing her support for sharks, maybe other people could too. Something else more powerful happened, down in the Cooks. They have a parliamentary system and also a traditional leadership system. And so the traditional chiefs are called the Ariki. And the head of the House of Ariki he's known as the king. He invited us to his home island to show his support for sharks. And I was there to tell them why they needed to protect sharks. Except there was one problem. They hated sharks. Sharks stole fish from their lines that they needed to feed their families. And so for me to try to make a case for them to protect sharks I needed to make a case that mattered to them. It wasn't enough to say that within 50 years we've wiped some species of shark populations down to just three percent. It wasn't enough for them. I needed to find something that mattered. We talked about how sharks were apex predators in many ecosystems how they balanced coral reef ecosystems. Balanced reef ecosystems meant more fish to feed your families. Healthy reefs also meant healthy oceans. Healthy oceans produce our oxygen. These are very important, simple facts that we could talk about that weren't known to these fishermen before.
I was feeling all right. And then a hand went up, and the reality of who I was trying to talk to sharks about sort of hit me all at once, and I found myself frozen with my toes stuck to the tile because I was barefoot, and in Polynesia. And I asked myself, Like, "how the hell did I get here?" Well, this is them. And you notice there is like a naïvely happy girl in the front. So, these are the guys that I had to try to talk to who had very real experiences with sharks. They're in canoes every day trying to feed their families and sharks are literally ripping the tuna off of their lines. And, so when the man who's sitting behind me in the turquoise shirt he raised his hand, told me how much he hated sharks. He literally said like, "I hate them. They terrorize me in my canoe. I wish they would all disappear from the planet." I'm like, "Oh, this is not going well." And then he said, "But I've learned something today. I wasn't sure of the importance of them to our reef. I have children, I have grandchildren and I would like for them to fish and for that reason I will support you." For me, that was the single most powerful moment of the entire two years of the campaign. And soon after that happened... We made front page of the paper. And this small group of farmers, fishermen voyagers, Miss South Pacific growers and fishermen, they came together and were successful in getting regulations that ban the import, export, sale, trade, possession and trans-shipment of sharks and rays in the entire exclusive economic zone of the Cook Islands. So, it was... an area the size three times of Texas. So, it's 772,000 square kilometers. And, it connected the existing Shark Sanctuaries in the world. So, it's now the largest contiguous Shark Sanctuary on the planet.
And while I was so proud of this group of local people the scientist in me had to step back and say like "Okay, this is great but is it going to work?" And so, I decided to try to combine all of the experiences I've had to create an organization called Sharks Pacific. And what we do is we... we combine science, we find political levers we work with local people and we try to tell the stories. Eleven thousand sharks have been killed in the past one hour. And that is by conservative estimates. I am asking you guys in the audience who are creative and passionate and connected join us in this fight 'cause we can do a lot better than extinction. Thank you.


text:
Q: If two maps' derivatives have unit length, then the derivative of the product is $\pm 1$ Let $M$ be a space and $I$ the unit interval.

Definition A map $f : I \to M$ is a parametrization by arc-length if $f$ maps $I$ diffeomorphically onto an open subset of $M$, and if the "velocity vector" $df_s(1)$ has unit length, for each $s\in I$.

Now let $f:I\to M$ and $g:J\to M$ be parametrizations by arc-length.

Claim The derivative of $g^{-1}\circ f$ is equal to $\pm 1$ everywhere.

Why is the claim true?
The derivative of $g^{-1}\circ f$ is $dg^{-1}\circ df=∂g^{-1}/∂f^1\cdot∂f^1/∂x$. Since $dg^{-1}$ and $df$ have unit length, $∂g^{-1}/∂f^1=\pm1$ and $∂f^1/∂x=\pm 1$ and the claim follows, I think.
How do we know that $f$ has only one component function? Is it because it is a diffeomorphism between $I$ and $f(I)$?

A: Note that $g^{-1} \circ f$ does not make sense unless $f$ takes values in the image of $g$.
It is true that the derivative of $g^{-1} \circ f$, which is a real number, has absolute value $1$ everywhere on $I$, so it must be $\pm 1$ everywhere. By continuity of $(g^{-1} \circ f)'$ and connectedness of $I$, it must be either $+1$ everywhere or $-1$ everywhere.
FYI, a careful little computation shows that the derivative of $g^{-1} \circ f$ at $t\in I$ is the unique real number $\alpha(t) := (g^{-1} \circ f)'(t)$ such that $f'(t) = \alpha(t)\,g'(s)$ where $s = g^{-1} \circ f (t)$. Note that in this equality, $f'(t)$ and $g'(s)$ are not real numbers but tangent vectors (at $f(t)$) to $M$.

redpajama_set_name: RedPajamaStackExchange


text:
NSW Health slammed by Ruby Princess inquiry report
Fiona CarruthersTravel editor
Aug 14, 2020 – 6.54pm
NSW Health missed a "significant spike" in the number of sick people on board the Ruby Princess ahead of its docking in Sydney on March 19, then allowed an "inexcusable" delay in testing a dozen swabs taken on board, says a report by the special commission of inquiry into the Ruby Princess debacle.
All 2647 passengers on board should have been tested for COVID-19, and disembarkation should not have occurred until the test results were in, says the 315-page report by Commissioner Bret Walker, SC, which was handed to the NSW government on Friday.
Had NSW Health properly communicated to Ruby Princess what constituted a suspicious case, rather than deeming the ship a ''low risk'', they would have realised at least 120 sick passengers already presented a high probability COVID-19 cluster, and needed to be kept isolated in their cabins on arrival into Sydney's Circular Quay.
The Ruby Princess cruise ship in Circular Quay in March. Kate Geraghty
The Carnival Corporation, which owns Princess Cruises, also should have made an onboard announcement to passengers that the ship had suspected COVID-19 cases.
The report's recommendations focus on ensuring changes to the NSW Human Biosecurity Officer's guidelines to reflect a more "precautionary public health approach" to the disembarkation process.
It also calls for improved co-ordination between a number of bodies, including the NSW Human Biosecurity Officers, the Commonwealth Department of Health
and NSW Health. This includes better understanding each agency's roles, and developing "more formal protocols for their interaction and communication".
The report describes the nation's single-biggest cluster of COVID-19 infections as a "sorry episode".
As of mid-May, the COVID-19 death toll from passengers aboard the Ruby Princess cruise had reached 22, while 712 passengers and 202 crew have tested positive.
The report describes the nation's single-biggest cluster of COVID-19 infections as a "sorry episode" that could have been avoided if NSW Health had not failed to await test results of swabs from passengers that were taken off the ship for testing from around 3am.
Instead, Ruby Princess was given the green light to begin disembarking its guests after daybreak on March 19.
All passengers on board the Ruby Princess should have been tested for COVID-19, and disembarkation should not have occurred until the test results were in, says the report. Kate Geraghty
This single act comprised a "large factor in this commission's findings as to the mistakes and misjudgments that caused the scattering of infected passengers", the report says.
Within hours of passengers being let loose to find their own way home – including taking Ubers, taxis, buses, trains and flights – three swabs taken from those on board Ruby Princess had come back as positive for COVID-19.
NSW Health also should have "ensured that cruise ships were aware of the change to the definition of a "suspect case" for COVID-19 made on March 10 by the Communicable Diseases Network Australia (CDNA)," the report says.
Under this upgraded definition, at least 120 people on board Ruby Princess would have met the criteria by March 19.
"The decision [by NSW Health] to assess the risk as "low risk" – meaning, in effect, "do nothing" – is as inexplicable as it is unjustifiable. It was a serious mistake," Mr Walker says.
''The decision [by NSW Health] to assess the risk as 'low risk' – meaning, in effect, 'do nothing' – is as inexplicable as it is unjustifiable. It was a serious mistake,'' Mr Walker says.
Princess Ruby is operated by Princess Cruises, which is owned by the American Carnival Corporation.
Mr Walker reserved some criticism for the parent company, saying Carnival should have ensured their on-board doctor, Dr Ilse von Watzdorf, was also made aware of the change to the CDNA "suspect case" definition.
"They should also have ensured that passengers and crew aboard the Ruby Princess were informed that there were suspect cases of COVID-19 on board," it says, adding "those persons meeting the definition of a suspect case should have been required to isolate in their cabins."
Given that by mid-March, after the Diamond Princess experience, anyone on a cruise ship was considered "to be close contacts" of even one case on board, the "logical and precautionary assumption should at least have justified the public health authorities taking steps to prevent passengers [and crew as well] from scattering into the community after disembarkation," Mr Walker writes.
The Australian Border Force was also singled out for initially advising passengers during the cruise that their 14-day period of self-isolation would commence from the date of departure from the last overseas port visited by the Ruby Princess, which was Napier on March 15.
This statement was later clarified during the disembarkation process on March 19.
However, yet another disturbing error occurred when authorities allowed passengers to take onward travel arrangements both interstate and internationally, which effectively breached the Public Health Order that came into effect on March 17, requiring all cruise ship passengers entering the State from any other country to isolate themselves in suitable accommodation for 14 days.
"Under the terms of the Public Health Order, the state government should have arranged suitable accommodation for all passengers who were not residents of the State," the report says, adding some passengers were symptomatic during transit.
Mr Walker points out the disaster continues to play out, given the "human consequences of the scattering upon disembarkation have not yet played out".
Fiona Carruthers has written and edited travel for the Financial Review for almost a decade. She has held senior roles with ABC Radio National, Deutsche Welle Radio, TIME and The Australian, and was deputy editor of Traveller. Email Fiona at fcarruthers@afr.com


"Ballin' Babes" is a new video series brought to you by Ballin' On a Budget in collaboration with our friends at Blacksun Productions.
In this series we will showcase some of the world's most attractive women doing fun and outrageous activates. In our 5th video we bring you the breathtaking Kylie James. Miss James is a personal trainer and model hailing from Australia's Gold Coast this mother of one has one of the most seductive bodies we have ever come across.
The Online Source For Action Sports, Style,Culture & Everything Inbetween. Updated Daily.
Shot on RED Epic "Lucy" by Dr. Dominik Muench.


In an experimental effort to freshen up the site, I've decided to start toying with various artwork styles per comic. Depending on the joke or type of humor, I'll use the art that best tells that story. "Late for Work" is a third new style that reads vertically as opposed to left to right. People seem to like the cat, so I thought I'd carry him through the new style. I hope you enjoy!


text:
There's something inside That you wanna say
High Fidelity (2000)
Quizzes: John Cusack Quiz
https://www.getyarn.io/yarn-clip/296b7598-b7c5-4849-b40a-f6e7af8bd50d
#ew
#laughing
#thankyou
(SINGING) There is something inside that you want to say
The Internship (2013)
♪ There's something about you ♪ ♪ that makes me wanna say, yeah ♪
Cloverfield (2008)
Isn't there something you wanna say?
Baby Daddy (2012) - S06E01 Family
The Birth of a Nation (2016)
Is there something you wanna say
there's something I wanna say that's always been very difficult
Is there something you wanna say to me?
Well, you say that there are family heirlooms inside your safety deposit box.
Lost (2004) - S01E21 Drama
Do you wanna say something?
Freaks and Geeks (1999) - S01E14 Drama
Lindsay, you wanna say something?
Rock the Kasbah (2015)
So... you wanna say something?
That's proof that there's something deep inside.
Wait, there's something I wanna say
Lois, there's something I wanna say.
He's Just Not That Into You (2009)
AII right, Iook, I wanna say something, okay?
So, immediately, I know that there's something in that box
There's SOMETHING inside there.
Easy A (2010)
...if there's something that you wanna talk about...
And there's something that I wanna tell you.
So, there had to have been something in that box
If she's as special as you say. she's gonna wanna hear...
Riverdale (2017) - S02E04 Chapter Seventeen: The Town That Dreaded Sundown
You wanna prove something?
Community (2009) - S06E02 Lawnmower Maintenance and Postnatal Care
I have something that I wanna say.
I... have something that I wanna say.
The bank says that there was nothing missing.
Cat Stevens-Wild World
You say you wanna start something new
You got something you wanna say?


text:
Q: Is there a combinatorial way to see the link between the beta and gamma functions? The Wikipedia page on the beta function gives a simple formula for it in terms of the gamma function.  Using that and the fact that $\Gamma(n+1)=n!$, I can prove the following formula:
$$
\begin{eqnarray*}
\frac{a!b!}{(a+b+1)!} & = & \frac{\Gamma(a+1)\Gamma(b+1)}{\Gamma(a+1+b+1)}\\
 & = & B(a+1,b+1)\\
 & = & \int_{0}^{1}t^{a}(1-t)^{b}dt\\
 & = & \int_{0}^{1}t^{a}\sum_{i=0}^{b}\binom{b}{i}(-t)^{i}dt\\
 & = & \int_{0}^{1}\sum_{i=0}^{b}\binom{b}{i}(-1)^{i}t^{a+i}dt\\
 & = & \sum_{i=0}^{b}\binom{b}{i}(-1)^{i}\int_{0}^{1}t^{a+i}dt\\
 & = & \sum_{i=0}^{b}\binom{b}{i}(-1)^{i}\left[\frac{t^{a+i+1}}{a+i+1}\right]_{t=0}^{1}\\
 & = & \sum_{i=0}^{b}\binom{b}{i}(-1)^{i}\frac{1}{a+i+1}\\
b! & = & \sum_{i=0}^{b}\binom{b}{i}(-1)^{i}\frac{(a+b+1)!}{a!(a+i+1)}
\end{eqnarray*}
$$
This last formula involves only natural numbers and operations familiar in combinatorics, and it feels very much as if there should be a combinatoric proof, but I've been trying for a while and can't see it. I can prove it in the case $a=0$:
$$
\begin{eqnarray*}
 &  & \sum_{i=0}^{b}\binom{b}{i}(-1)^{i}\frac{(b+1)!}{0!(i+1)}\\
 & = & \sum_{i=0}^{b}(-1)^{i}\frac{b!(b+1)!}{i!(b-i)!(i+1)}\\
 & = & b!\sum_{i=0}^{b}(-1)^{i}\frac{(b+1)!}{(i+1)!(b-i)!}\\
 & = & b!\sum_{i=0}^{b}(-1)^{i}\binom{b+\text{1}}{i+1}\\
 & = & b!\left(1-\sum_{i=0}^{b+1}(-1)^{i}\binom{b+\text{1}}{i}\right)\\
 & = & b!
\end{eqnarray*}
$$
Can anyone see how to prove it for arbitrary $a$? Thanks!

A: Using partial fractions, we have that
$$
\frac{1}{(a+1)(a+2)\dots(a+b+1)}=\frac{A_1}{a+1}+\frac{A_2}{a+2}+\dots+\frac{A_{b+1}}{a+b+1}\tag{1}
$$
Use the Heaviside Method; multiply $(1)$ by $(a+k)$ and set $a=-k$ to solve $(1)$ for $A_k$:
$$
A_k=\frac{(-1)^{k-1}}{(k-1)!(b-k+1)!}=\frac{(-1)^{k-1}}{b!}\binom{b}{k-1}\tag{2}
$$
Plugging $(2)$ into $(1)$, yields
$$
\frac{a!}{(a+b+1)!}=\sum_{k=1}^{b+1}\frac{(-1)^{k-1}}{b!}\binom{b}{k-1}\frac{1}{a+k}\tag{3}
$$
Multiplying $(3)$ by $b!$ and reindexing, gives us
$$
\frac{a!b!}{(a+b+1)!}=\sum_{k=0}^{b}(-1)^k\binom{b}{k}\frac{1}{a+k+1}\tag{4}
$$
and $(4)$ is your identity.

Update: Starting from the basic binomial identity
$$
(1-x)^b=\sum_{k=0}^b(-1)^k\binom{b}{k}x^k\tag{5}
$$
multiply both sides of $(5)$ by $x^a$ and integrate from $0$ to $1$:
$$
B(a+1,b+1)=\sum_{k=0}^b(-1)^k\binom{b}{k}\frac{1}{a+k+1}\tag{6}
$$

A: Here's a combinatorial argument for $a!\,  b!  =  \sum_{i=0}^{b}\binom{b}{i}(-1)^{i}\frac{(a+b+1)!}{(a+i+1)}$, which is just a slight rewrite of the identity you want to show.
Suppose you have $a$ red balls numbered $1$ through $a$, $b$ blue balls numbered $1$ through $b$, and one black ball.
Question: How many permutations of the balls have all the red balls first, then the black ball, and then the blue balls?
Answer 1: $a! \,b!$. There are $a!$ ways to choose the red balls to go in the first $a$ slots, $b!$ ways to choose the blue balls to go in the last $b$ slots, and $1$ way for the black ball to go in slot $a+1$.
Answer 2: Let $A$ be the set of all permutations in which the black ball appears after all the red balls (irrespective of where the blue balls go).  Let $B_i$ be the subset of $A$ such that the black ball appears after blue ball $i$.   Then the number of permutations we're after is also given by $|A| - \left|\bigcup_{i=1}^b B_i\right|$.  Since the probability that the black ball appears last of any particular $a+i+1$ balls is $\frac{1}{a+i+1}$, and there are $(a+b+1)!$ total ways to arrange the balls, by the principle of inclusion-exclusion we get $$\frac{(a+b+1)!}{a+1} - \sum_{i=1}^{b}\binom{b}{i}(-1)^{i+1}\frac{(a+b+1)!}{(a+i+1)} =  \sum_{i=0}^{b}\binom{b}{i}(-1)^{i}\frac{(a+b+1)!}{(a+i+1)}.$$

A: Seven years later I found another way to attack this. Define $f(b, a) = \frac{a!b!}{(a+b+1)!}$ and $h(b, a) = \sum_{i=0}^{b}\binom{b}{i}(-1)^{i}\frac{1}{a+i+1}$. To connect the two, we define $g$ such that $g(0, a) = \frac{1}{a + 1}$ and $g(b + 1, a) = g(b, a) - g(b, a + 1)$ and prove by induction in $b$ that $f = g = h$. In each case the base case is straightforward and we consider only the inductive step.
$$
\begin{eqnarray*}
& & g(b + 1, a) \\
& = & g(b, a) - g(b, a + 1) \\
& = & f(b, a) - f(b, a + 1) \\
& = & \frac{a!b!}{(a+b+1)!} - \frac{(a+1)!b!}{(a+b+2)!} \\
& = & \frac{a!b!(a + b + 2)}{(a+b+2)!} - \frac{a!b!(a+1)}{(a+b+2)!} \\
& = & \frac{a!b!(b+1)}{(a+b+2)!} \\
& = & \frac{a!(b+1)!}{(a+b+2)!} \\
& = & f(b+1, a)\\
\end{eqnarray*}
$$
$$
\begin{eqnarray*}
& & g(b + 1, a) \\
& = & g(b, a) - g(b, a + 1) \\
& = & h(b, a) - h(b, a + 1) \\
& = & \left(\sum_{i=0}^{b}\binom{b}{i}(-1)^{i}\frac{1}{a+i+1}\right) - \left(\sum_{i=0}^{b}\binom{b}{i}(-1)^{i}\frac{1}{a+i+2}\right) \\
& = & \frac{1}{a+1} + \left(\sum_{i=1}^{b}\binom{b}{i}(-1)^{i}\frac{1}{a+i+1}\right) - \left(\sum_{i=0}^{b-1}\binom{b}{i}(-1)^{i}\frac{1}{a+i+2}\right) - (-1)^{b}\frac{1}{a+b+2}\\
& = & \frac{1}{a+1} + \left(\sum_{i=1}^{b}\binom{b}{i}(-1)^{i}\frac{1}{a+i+1}\right) + \left(\sum_{i=1}^{b}\binom{b}{i-1}(-1)^{i}\frac{1}{a+i+1}\right) + (-1)^{b+1}\frac{1}{a+b+2}\\
& = & \frac{1}{a+1} + \left(\sum_{i=1}^{b}\left(\binom{b}{i} + \binom{b}{i-1}\right)(-1)^{i}\frac{1}{a+i+1}\right) + (-1)^{b+1}\frac{1}{a+b+2}\\
& = & \frac{1}{a+1} + \left(\sum_{i=1}^{b}\binom{b+1}{i}(-1)^{i}\frac{1}{a+i+1}\right) + (-1)^{b+1}\frac{1}{a+b+2}\\
& = & \sum_{i=0}^{b+1}\binom{b+1}{i}(-1)^{i}\frac{1}{a+i+1} \\
& = & h(b + 1, a) \\
\end{eqnarray*}
$$


text:
How real-time progress monitoring reduces rework and increases productivity
Most people in the construction industry have a story to tell, often it's humorous: a column in the wrong place, missing walls or a stairway to nowhere. But all these stories are costing us time and money.
We believe that the root cause of many of these issues lies in the fact that while we are designing digitally we are still constructing manually, software tools have developed rapidly but onsite tools have remained the same. Buildings are complex, with even simple developments requiring tens of thousands of elements.
Currently, Site managers have no way of quickly and accurately comparing as-built to the digital model, relying either on spot checks which are slow, labour intensive and not fully representative.
Put simply, if you cannot measure it you cannot manage it and if you don't understand a process objectively you will never improve it.
At Scaled Robotics we are bridging the gap between the digital model and the physical job site to verify work and provide objective analysis for staff to make better decisions quickly.
In this case study, we will demonstrate how on an exceptionally challenging site we were able to automate the quality assessment of the structural works within 24 hours. Providing critical insight at the right time into a complex project that saved the construction team both time and money.
Highlighting areas where we caught significant defects, streamlined documentation and improved coordination. Mitigating risk to keep management focused on delivering the project.
To demonstrate the product's capabilities we set up a test case. Taking a 9-floor hotel building, we analyzed data from 3 floors to verify quality and track progress. This constituted 3,500 m2 of built area and over 4,000 elements.
The test demonstrated dramatic reductions in rework costs, increased collaboration and reduction in friction. Delivering over €50,000 of direct savings on rework costs whilst improving overall quality and productivity.
3,500 m2 and over 4,000 elements
analyzed automatically in under 24 hours
The site is laser scanned.
Raw laser scan data uploaded to our cloud platform
Those scans are automatically processed and compared to the digital model.
Displayed for the user in a clear interface.
This analysis is fully automated by our computer vision and machine learning algorithms
This test focused predominantly on the structural steel and concrete phase of construction.
Over 4,000 elements were analyzed automatically overnight.
Results were delivered on an easy to use web-based viewer, where data could be searched for.
The user required used a regular computer to access this complex dataset.
Catching errors in real-time
In total, we estimate a reduction in re-work of between €50,270 and €67,190.
Approximately 1 week of working hours saved by the site team.
Flagging high-risk issues in hours, not days or weeks
There are a number of benefits our users found through using our software platform.
Catching issues early is crucial to reduce the impact they will have on the building project. The longer it takes to discover an issue the more expensive it is to resolve. On this project, this was exemplified in the reservations / block-out results, you can find details on this in the later section "Real-time error example".
Free up time and increase productivity
Our software saves site management time, issues are brought up ahead of time which reduces the severity and complexity of the issue which saves management time. Instead of manually checking thousands of elements to be 100% sure there are no issues staff can focus their energy on high-risk issues. That is time which can be reinvested into the project to proactively identify and solve problems that can reduce rework or warranty claims, and have a positive impact on margins. This is exemplified in how thousands of elements were filtered to bring to management attention the most damaging issues, in this case, reservations / blockouts, this is highlighted in the later section "Real-time error example"
Objective information about subcontractor performance can also be used to improve processes and actively prevent issues from becoming chronic within a project.
If an issue is identified it means nothing unless it can be clearly communicated to the relevant parties. One centralized automatically updated place for information means that fewer pieces of information fall through the cracks or are underutilized. In this case, objective information was used to collaborate with subcontractors and fix issues without the usual effort.
Automatic Documentation
Having that single source of documentation for site management allows staff to go back to previous dates and evaluate the state of the site instead of pouring through documentation. This pays dividends in avoiding costly litigation or conflict with stakeholders to recover costs, this is covered in more detail in "Documentation, communication and litigation".
Working proactively instead of reactively reduces risk
Real-time error example
A great example would be concrete reservations/block outs. These voids in the concrete for services are often misplaced or missing causing ripples of issues through a project because of the number of dependent tasks later in the programme. The value of catching this early is significant because traditionally these kinds of issues would be caught months later when the next trade relying on that void for services being accurate could no longer do there work. Causing disruptions, emergency work, possible health and safety considerations and extra costs.
Over 3 floors there were 15% were missing and 20% were not in the correct position. Each of these issues had not been previously detected.
As shown in the image above the BIM and actual site conditions do not match. The software brings this to the user's attention in a clear concise way, to quickly diagnose and communicate a critical issue.
Stakeholders can highlight these issues in 5 mouse clicks as opposed to hours or days of manual work onsite. Sharing those issues with the right people to make better decisions with better data.
15% of reservations were missing
Use data for your competitive advantage
Documentation, communication and litigation
We discovered with the customer that having accurate documentation for work pays dividends across the project lifetime helping to reduce the impact of litigation. Having an objective source truth on progress and quality helps General Contractors hold subcontractors to account and slash litigation costs.
Once an issue has been highlighted early it is easier to resolve before payment has been made. Opposed to addressing hard to prove issues months later when that subcontractor has moved to another job and them incurring extra costs impacts their ability to fix problems.
Objective truth documentation helps reduce friction and cut down on extra costs. Our customer estimates that of every issue that reaches litigation 40% of the value is recovered while the remaining 60% is wrapped up in legal fees, documentation and time wasted.
While it may be unrealistic to entirely eliminate rework, litigation or all inefficiencies the fact is most projects typically suffer from far too much of it. The Scaled Robotics software platform provides the tools for site management to take a big chunk out of the problem helping to save significant time and money. This pilot demonstrated a significant return on investment both in direct costs and productivity gains.
On this project, we highlighted the reservations (block-outs) but on the next, it could be any number of issues that were overlooked, that risk is always there but reducing that uncertainty helps deliver projects on time and on budget.
The benefits felt from this test have now led to a longer-term deployment which we are undertaking currently and look forward to sharing the results.
"The technology will streamline quality assurance processes by replacing subjective assessments with empirical and reliable data, delivered in an open and transparent platform."
Pau Beso AF Gruppen


With the Mainstays 8-Cube Bookcase, arranging the perfect library in an elegant style to match almost any room is simple with its modern design that is available in white or espresso finishes. This sturdy storage unit features an open-back construction and an intricate geometric style for eight divided storage and display areas. Easy, two-person assembly helps make this attractive bookshelf a useful and functional conversation piece in any living room, family room, or den. The Mainstays 8-Cube stands an impressive 68.5 inches tall for displaying an expansive library in large and medium sized rooms where smart, efficient storage is a priority. The eight geometric spaces create a smart and stylish design for books, photo albums, vinyl records, DVDs, CDs, and more to deliver a functional bookcase that is perfect for large and medium collections. This well-designed storage unit can also be used for displaying photography, artwork, collectibles, Mainstays baskets, houseplants, or for simply keeping much needed items at hand for easy access.
I actually got this product on sale and it has exceeded my expectations. You need patience when putting it together and recommend using a electric screw driver because there are a lot of screws. I also recommend using the included wall mounts if it will be placed on carpet.
The units were easy to assemble! They look just as described. I wish the screws were capped white or a cover was included but over all a great piece!
For only 40 dollars this is a beautiful display and is bigger then I expected it!
Can't complain for the price I paid. Serves the purpose perfectly.
For what I paid (forty on sale) this thing is amazing. I really love the height, the color, the overall size, and the asymmetrical design. It's not incredibly sturdy, but I never planned to use it for books. The finish isn't perfect, either. Please note that the package weighs 72 pounds! FedEx would not even carry it up the six steps to my porch. I put it together by myself, with no power tools. The instructions are straightforward and every piece has a letter on it that corresponds with the pictures. It took maybe two hours and was actually a fun challenge - like a puzzle! In short, it's a great value for the price, and exactly what I needed. If you want something that looks high-end, this is not the bookcase for you. But I love it.
Great packaging. Just a small scrape on the corner of a piece of wood but nothing major. Very easy to assemble! You don't need two people. One person can do it. I did it and I'm only 5'1. Rich in color-just dust to clean and looks beautiful!
I purchased mine on Friday and it arrived on Monday. It arrived very well packed not a piece was missing and had one extra dowel. Took me and my two daughters ages 12 & 14, one hour to build. Nothing but dowels, screws and tap screws. You could use an electric drill to make it go faster but we used a hand phillips screwdriver. Directions were exactly as stated. Looks great for the price!
This is a good bookcase for the price. It came on time and was well packaged. No damaged pieces and everything was included. It was very easy to assemble. Although I knew the measurements, in the area where I have it, it looks a little shorter than I expected, but it still looks good. I'm actually thinking of buying another one and putting it on the other side of my TV stand to create an entertainment area.
We bought 2: One arrived broken, One looks great!
The long side boards were cracked on delivery, don't accept your box if it arrives like my picture. We bought two shelving units. We had to haul the 70 lb broken box back to the store. The other I got together in 45 minutes. Once we unpacked and organized, it was super easy to assemble. The shelf is a lovely addition, looks sharp and clean. Did need more stickers to cover screw holes.
I bought two of these book cases to divide my studio space into a living and bedroom space.The boxes were pretty heavy, I picked up the boxes in store and had to carry them to my apartment all by myself. I put these together and after doing the first one the second one was a breeze. I think you should start by putting in all the wooden peg things, then putting the pieces together, followed by putting the screws in. I did this all manually but I think using a power tool in a LOW setting will be very helpful if you are putting them together by your self. My hands were so achy half way through!! Otherwise these are very stylish and the bookshelves are really cute and are different from the square ones that they will sell at ikea for tripple the price! They are about 5'6 ft standing. Its not really wood and it can be a little flimsy if you nudge them too hard. I have them up on a carpet they are not bolted to my wall, I do not have children so it is safe for me. They are very cute and for the price paid the quality is worth it!


text:
Since 2019, the Center for Animal Health and Food Safety (CAHFS) has hosted visiting scholars as part of the U.S. Department of Agriculture (USDA) Foreign Agricultural Service program's Cochran Fellowship.
Roughly 600 Cochran fellows visit the U.S. for each year to work with universities, government agencies, and private companies to receive hands-on training related to current issues in agricultural trade.
The University of Minnesota has hosted several Cochran Fellowship programs in the past two decades, with successful training programs composed of short presentations, interactive sessions, and site visits. Faculty at the University of Minnesota and their global partners are at the forefront of research on global health and food systems challenges, and prioritize crafting learning modules that bring critical scientific knowledge to working professionals.
Cochran Fellows from Turkey complete a multi-sectoral process mapping activity during their visit to the University
Cochran Fellowships at CAHFS
Turkey: Highly pathogenic avian influenza
In June 2019, CAHFS hosted six fellows from Turkey as part of the USDA's Cochran Fellowship. The fellows learned about risk assessment and how to manage animal disease outbreaks, with a focus on highly pathogenic avian influenza (HPAI).
Fellows saw biosecurity methods that U.S. farms use to keep poultry farms healthy from infectious diseases. They also visited the U of M Veterinary Diagnostic Laboratory and disease surveillance laboratories for the Minnesota poultry industry in Willmar, Minnesota.
Ghana and Kenya: International trade policy
Cochran Fellows from Kenya and Ghana visited the University during a snowy Minnesota December
In December 2019, two fellows from Kenya and one from Ghana traveled to the University of Minnesota to learn about international trade policy. Cochran Fellows received training on sanitary and phytosanitary measures (SPS) agreement and risk analysis.
The training provided the fellows with an in-depth understanding of SPS regulations and how the World Trade Organization's SPS Agreement facilitates international trade using science-based risk analysis approaches.


Anna and Jay with the Bruker D8 ADVANCE X-ray Powder Diffractometer at the University of Georgia Geology lab, May 1, 2017. Photo: Paul Schroeder.
Anna Wade (visiting from Duke University) and Jay Austin (based at the University of Georgia) are collaborating by using X-ray Diffraction (XRD) to determine clay minerals in the fine fraction and relative abundances of minerals in bulk samples. Identifying and quantifying phases in the Critical Zone is a challenge. Here they are setting up an XRD experiment in the UGA Geology lab. Methodologies for sample preparation, data collection, and subsequent quantitative model simulations are key for good precision and accuracy. Models being used in the process include NEWMOD for simulating mixed-layer clays structures and the Rietveld refinement method for quantifying model abundances.